C语言学习10

文章目录
  1. 1. 文件
    1. 1.1. 文件类型指针
    2. 1.2. 文件的打开与关闭
      1. 1.2.1. 打开文件
      2. 1.2.2. 关闭文件
    3. 1.3. 文件的读写
      1. 1.3.1. 以字符形式读写文件
      2. 1.3.2. 以字符串形式读写文件
      3. 1.3.3. 以数据块的形式读写文件
      4. 1.3.4. 格式化读写文件
      5. 1.3.5. 随机读写文件

文件

本文将详述C语言中关于文件的相关知识。

文件是数据源的一种,主要的作用是保存数据。
在操作系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。对这些文件的操作,等同于对磁盘上普通文件的操作。列如:
●通常把显示器称为标准输出文件,printf就是向这个文件输出数据。
●通常把键盘称为标准输入文件,scanf就是从这个文件读取数据。
常见输出设备对应的文件:

文件 硬件设备
stdin 标准输入文件,一般指键盘: scanf() getchar()…
stdout 标准输入文件,一般指显示器 print() putchar()等
stderr 标准错误文件,一般指显示器;perror()等
stdprn 标准打印文件,一般指打印机

C语言把文件分为ASCII文件和二进制文件。ASCII文件又称文本文件。
文件流:指数据在文件和内存之间传递的过程。
输入流:指数据从文件复制到内存的过程。
输出流:从内存保存到文件的过程。

文件与内存的关系

数据流(Data Stream):指数据在数据源和程序(内存)之间传递的过程。
输入流(Input Stream):数据从数据源到(内存)程序的过程。
输出流(Output Stream):数据从程序(内存)到数据源的过程。
文件输入输出方式也称”存取方式”。C语言中,文件有两种存取方式:顺序存取和直接存取。

文件类型指针

可以用结构体类型来定义文件类型的指针变量,一般形式为:
FILE *fp;
fp是一个指向FILE结构体类型的指针变量。

文件的打开与关闭

打开文件

1.调用形式:
FILE *fp = fopen(文件名,文件使用方式);
●函数返回一个指向FILE类型的指针。
●无论哪种使用方式,当打开文件时出现错误,fopen函数都将返回NULL。

2.常用文件打开方式及说明:
【控制读写权限(必须指明)】

打开方式 说明
r 以”只读”方式打开文件。只允许读取,不允许写入。文件必须存在,否则打开失败。
w 以”写入”方式打开文件。如果文件不存在,那么创建一个新文件,如果文件存在,那么清空文件内容(相当于删除源文件,再创建一个新文件。)
a 以”追加”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件末尾(文件原有的内容保留)
r+ 以读写方式打开文件。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败。
w+ 以”写入/更新”方式打开文件,相当于w和r+叠加的效果。首先建立一个新文件,进行写操作,随后可以从头开始读。如果指定文件已存在,则原有内容会被清空。
a+ 以”追加/更新”方式打开文件,相当于a和r+叠加的效果。既可以读也可写,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件末尾。

【控制读写方式(可省略)】

打开方式 说明
“t” 文本文件。如果不写,默认为”t”。
“b” 二进制文件

●调用fopen()函数时必须指明读写权限,但是可以不指明读写方式(此时默认为”t”)
●读写权限和读写方式可以组合使用,但必须以读写权限开头。
●整体来说,文件打开方式由r、w、a、t、b、+等6个字符拼成,各字符含义如下:

r(read) w(write) a(append) t(text) b(banary) +
追加 文本文件 二进制文件 读和写

关闭文件

文件一旦使用完毕,应该用fclose()函数把文件关闭,以释放相关资源,避免数据丢失。
1.fclose()的用法为:
int fclose(FILE *fp);
fp为文件指针,如 fclose(fp);

2.使用说明:
●若对文件的操作方式为”读”方式,则经以上函数调用之后,要使文件指针与文件脱离联系。可以重新分配文件指针去指向其他文件。
●若对文件的操作方式为”写”方式,则系统首先把该文件缓冲区中的剩余数据全部输出到文件中,然后使文件指针与文件脱离联系。
●在完成了对文件的操作后,应当关闭文件,否则文件缓冲区中剩余数据就会丢失。
●当执行了关闭操作后,成功则函数返回0,否则返回非0。

文件的读写

以字符形式读写文件

以字符形式读写文件时,每次可以从文件读取一个字符,或者向文件中写入一个字符。主要使用两个函数,分别是fgetc()和fputc()。
◆字符读取函数fgetc():
fgetc是 file get char的缩写,意为从指定文件中读取一个字符。
一般形式: int fgetc(FILE *fp);
fp为文件指针;fgetc()读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF.
EOF(End of File)表示文件末尾,是在stdio.h中定义的宏,它的值往往为-1是负数。

在读取文件时,文件内部由系统设置一个位置指针,用于指向当前读写的位置;在文件打开时总是指向文件中的第一个字节,每次fgetc()使用后该位置指针会向后移动一个字节,所以可以连续使用fgetc()读取多个字符。

【程序示例】在屏幕上显示D:\\demo.txt文件的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
int main(){
FILE *fp;
char ch;
//如果文件不存在,给出提示并退出
if((fp=fopen("D:\\demo.txt","rt"))==NULL){
puts("Fail to open file!");
exit(0);
}
//每次读取一个字节,直到读取完毕
while((ch=fgetc(fp))!=EOF){
putchar(ch);
}
putchar('\n');//输出换行符
fclose(fp);
return 0;
}

对EOF的说明:EOF本意指文件末尾,但读取文件出错时也会返回EOF。
要进一步判断读取状态可借助stdio.h中的feof()和ferror()函数。

feof()函数:用于判断文件内部指针是否指向末尾,当指向文件末尾时返回非零值,否则返回为0。
一般形式:
int feof(FILE *fp);
ferror()函数:用于判断文件操作是否出错,当文件操作出错时返回非零值,否则返回为0。
一般形式:
int ferror(FILE *fp);
◆字符写入函数fputc():
fputc 是file output char 的缩写,意为向指定文件写入一个字符。
一般形式:
int fputc(int ch,FILE *fp);
ch为要写入的字符,fp为文件指针。fputc()写入成功时返回写入的字符,失败时返回EOF,返回值类型为int即可容纳这个值(负数)。
  语句示列:把字符’a’写入fp所指向的文件中
fputc(‘a’,fp); 或 char ch=’a’; fputc(ch,fp);
【程序示例】从键盘输入一行字符,写入文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
int main(){
FILE *fp;
char ch;
//判断文件是否打开成功
if((fp=fopen("D:\\demo.txt","wt+"))==NULL){
puts("Fail to open file!");
exit(0);
}

printf("Input a string:\n");
//每次从键盘读取一个字符并写入文件
while((ch=getchar())!='\n'){
fputc(ch,fp);
}
fclose(fp);
return 0;
}

fgetc()和fputc()函数每次只能读写一个字符,速度较慢;实际开发中往往读写字符串或数据块。

以字符串形式读写文件

◆读取字符串函数fgets():
fgets()函数用来指定文件中读取一个字符串,并保存到字符数组中。
一般形式:
char *fgets(char *str,int n,FILE *fp);
str为字符数组,n为要读取的字符数目,fp为文件指针。
返回值:读取成功时返回字符数组首地址,也即str;读取失败时返回NULL;如果开始读取文件内部指针已指向了末尾,那么读取不到任何文字,也返回NULL。
▲注意:读取到的字符串会在末尾自动添加’\0’,n个字符有n+1个长度,遇到换行符会一并读取到字符串。

【程序示例】一行一行地读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include<stdlib.h>
#define N 100

int main(){
FILE *fp;
char str[N+1];
if((fp=fopen("d:\\demo.txt","rt"))==NULL){
puts("Fail to open file!");
exit(0);
}

while(fgets(str,N,fp)!=NULL){
printf("%s",str);
}
fclose(fp);
return 0;
}

◆写字符串函数fputs():
fputs()函数用来向指定的文件写入一个字符串。
一般形式为:
int fputs(char *str,FILe *fp);
str为要写入的字符串,fp为文件指针。写入成功则返回非负数,否则返回EOF。

【程序示例】向d:\\demo.txt文件中追加一个字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
int main(){
FILE *fp;
char str[102]={0},strTemp[100];
if((fp=fopen("D:\\demo.txt","at+"))==NULL){
puts("Fail to open file!");
exit(0);
}
printf("Input a string:");
gets(strTemp);
strcat(str,"\n");
strcat(str,strTemp);
fputs(str,fp);
fclose(fp);
return 0;
}

以数据块的形式读写文件

如果需要读取多行内容,需要使用fread()函数;相应地写入函数为fwrite()。
数据块:即若干个字节的数据,可以是一个字符、一个字符串或多行数据,并没有什么限制。
fread()原型:
size_t fread(void *ptr,size_t size,size_t count,FILE *fp);
fwrite()原型:
size_t fwrite(void *ptr,size_t size,size_t count,FILE fp);
说明:
●ptr为内存区块的指针,它可以是数组、变量、结构体等。fread()中的ptr用来存放读取到的数据,而fwrite()中的ptr用来存放要写入的数据。
●size表示每个数据块的字节数
●count表示要读写的数据块的块数。
●fp表示文件指针
●理论上每次读写 size
count个字节的数据
●size_t是typedef定义的无符号整型数据类型,表示数量。
●返回值:返回成功读写的块数,也即count。
若返回值小于count:

fwrite() fread()
肯定发生了写入错误,可用ferror()函数检测 可能读到了文件末尾,可能发生了错误,可用ferror()、feof()检测

rewind(fp):将文件中的指针重新定位到文件开头。

【程序示例】从键盘输入两个学生数据,写入一个文件中,再次读出这两个学生数据到屏幕上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<stdio.h>
#define N 2
struct stu{
char name[10]; //姓名
int num; //学号
int age; //年龄
float score; //成绩
}boya[N],boyb[N],*pa,*pb;

int main(){
FILE *fp;
int i;
pa = boya;
pb = boyb;
if((fp=fopen("d:\\demo.txt","wb+"))==NULL){
puts("Fail to open file!");
exit(0);
}
//从键盘输入数据
printf("Input data:\n");
for(i=0;i<N;i++,pa++){
scanf("%s %d %d %f",pa->name,&pa->num,&pa->age,&pa->score);
}

//将数组数据写入文件
fwrite(boya,sizeof(struct stu),N,fp);
//将文件指针重置到文件开头
rewind(fp);
//从文件读取数据并保存到数据boyb
fread(boyb,sizeof(struct stu),N,fp);
//输出数组boyb中的数据
for(i=0;i<N;i++,pb++){
printf("%s %d %d %f\n",pb->name,pb->num,pb->age,pb->score);
}
fclose(fp);
return 0;
}

格式化读写文件

以磁盘文件作为读写对象的格式化读写函数fscanf()和fprintf()。
一般形式:
int fscanf(FILE *fp,char *format,…);
int fprintf(FILE *fp,char *format,…);
fp为文件指针,format为格式控制字符串,…表示参数列表。
返回值:
fprintf()返回成功写入字符的个数,失败则返回负数。
fscanf()返回参数列表中被成功赋值的参数个数。

随机读写文件

所谓随机读写指移动文件内部的位置指针后再进行读写。经常用于实际开发中读取文件的中间部分。
实现随机读写的关键是按要求移动位置指针,这称为文件的定位。
rewind()函数用于将位置指针移动到文件开头,原型为:
void rewind(FILE *fp);
fseek()函数用于将位置指针移动到任意位置,它的原型为:
int fseek(FILE *fp,long offset,int origin);
说明:
●fp为文件指针
●offset为偏移量,也就是要移动的字节数。offset为正,向后移动;为负,向前移动。
●origin为起始位置,也就是从何处开始计算偏移量。C语言的起始位置有以下三种,如下:

起始位置 常量名 常量值
文件开头 SEEK_SET 0
当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2

●fseek一般用于二进制文件。


版权声明

Scholar’s Blog by scholargeek is licensed under a Creative Commons BY-NC-ND 4.0 International License.
董仕麟创作并维护的scholargeek博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证

本文首发于Scholar’s Blog博客,版权所有,侵权必究。

本文永久链接:https://scholargeek.github.io/2018/02/20/C%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A010/

更新日期:


本站总访问量