参考资料:《全国计算机等级考试二级教程——C语言程序设计》、《21天学通C语言》
文件名
在处理磁盘文件时必须使用文件名。
在C程序中,文件名还需要包含路径信息,如果指定的文件名没有路径,则假定该文件位于操作系统默认的当前目录中。
文件指针
文件指针实际上是一个指向结构体类型的指针。
一般称上面提到的结构体类型名为FILE,可以用此类型名来定义文件指针。定义文件类型指针变量的一般形式为:
FILE *指针变量名
例如:
FILE *fp1, *fp2;
fp1和fp2均被定义为指向文件类型的指针变量,称为文件指针。
打开文件
打开文件可以使用fopen函数,其调用形式为:
fopen(文件名, 文件使用方式);
函数返回一个FILE类型的指针,如:
FILE *fp;
fp = open("file_a", "r");
fopen函数中有两个字符串作为参数。第一个字符串中包含了进行读、写操作的文件名,用来指定要打开的文件。
第二个字符串指定了文件的使用方式。
若fopen函数调用成功,函数返回一个FILE类型的指针,赋给文件指针变量fp,从而把指针fp与文件file_a关联起来了,也就是说,指针fp指向了文件file_a。
常用的文件使用方式及其含义如下:
r:为读而打开文本文件。当使用这种方式时,对打开的文件只能进行“读”操作。
rb:为读而打开一个二进制文件。其余功能与r相同。
w:为写而打开文本文件。这时,如果指定的文件不存在,系统将用在fopen调用中指定的文件名建立一个新文件;如果指定的文件已存在,则将从文件的起始位置开始写。注意:文件中原有的内容会全部丢失。
wb:为写而打开一个二进制文件。可以在指定文件位置进行写操作,其余功能与w相似。
a:为在文件后面添加数据而打开文本文件。这时,如果指定的文件不存在,系统将用在fopen调用中指定的文件名建立一个新文件;如果指定的文件已存在,则文件中原有的内容将保存,新的数据写在原有内容之后。
ab:为在文件后面添加数据而打开一个二进制文件。其余功能与a相同。
r+:为读和写而打开文本文件。若指定的文件已经存在,既可以对该文件进行读,也可以对该文件进行写,在读和写操作之间不必关闭文件。对于文本文件来说,读和写总是从文件的起始位置开始,在写新的数据时,只覆盖新数据所占的空间,其后的老数据不会丢失。
rb+:为读和写而打开一个二进制文件。功能与r+相同,但是可以由位置函数来设定读和写的起始位置。
w+:首先建立一个新文件,进行写操作随后可以从头开始读。如果指定的文件已存在,则原有文件的内容会丢失。
wb+:功能与w+相同,但是在随后的读和写时,可由位置函数来设置读和写的起始位置。
a+:功能与a相同,只是在文件尾部添加新数据之后,可以从头开始读。
ab+:功能与a+相同,只是在文件尾部添加新数据之后,可由位置函数来设置读和写的起始位置。
关闭文件
关闭文件可调用库函数fclose来实现,其调用形式为:
fclose(文件指针);
若fp是指向文件file_a的文件指针,当执行力fclose(fp);之后:
- 若对文件file_a的操作方式为“读”方式,则将使文件指针fp与文件file_a脱离联系。在此之后,可以重新分配文件指针fp去指向其他文件。
- 若对文件file_a的操作方式为“写”方式,则系统首先把文件缓冲区的剩余数据全部输出到文件中,然后使文件指针fp与文件file_a脱离联系。
所以,在完成了对文件的操作之后,应该关闭文件,否则文件缓冲区的数据会丢失。
当成功执行了关闭操作,fclose函数返回0,否则返回非0。
调用getc(fgetc)和putc(fputc)函数进行输入和输出
调用putc(fputc)函数输出一个字符
putc函数的调用形式如下:
putc(ch, fp);
ch是待输出的某个字符,可以是一个字符常量或字符变量。fp是文件指针。
这条语句的功能是将字符ch写到文件指针fp所指的文件中去。
如果输出成功,putc函数返回所输出的字符,如果输出失败,则返回一个EOF值(EOF是一个值为-1的符号常量)。
fputc的调用形式与putc完全相同。
调用getc函数输入一个字符
getc函数的调用形式如下:
ch = getc(pf);
pf是文件指针。
函数getc的功能是从pf指定的文件中读入一个字符。
上述表达式是从文件中读入一个字符并赋给变量ch。
判断文件结束函数feof
以EOF作为文件结束标志的文件,必须是文本文件。
当把数据以二进制形式存放到文件中时,就会有-1的值出现,这时不能采用EOF作为二进制文件的结束标志。为了解决这个问题,可以使用feof函数,用来判断文件是否结束。
如果遇到文件结束,函数feof的值为1,否则为0。
feof既可以判断二进制文件是否结束,也可以判断文本文件是否结束。
fscanf函数和fprintf函数
fscanf函数
fscanf函数只能从文本文件中按格式输入。
fscanf函数的调用形式如下:
fscanf(文件指针, 格式控制字符串, 输入项表);
例如:
文件指针fp已经指向一个已打开的文本文件,a和b分别为整型变量,以下语句从fp所指的文件中读入两个整型变量并且放入a和b中:
fscanf(fp, "%d%d", &a, &b);
注意:文件中的两个整数用空格或跳格符等隔开。
以下两条语句等价:
fscanf(stdin, "%d%d", &a, &b);
scanf("%d%d", &a, &b);
fprintf函数
fprintf函数按格式将内存中的数据转换成对应的字符,并以ASCII码的形式输出到文本文件中。
fprintf函数的调用形式如下:
fprintf(文件指针, 格式控制字符串, 输出项表);
例如:
文件指针fp已经指向一个已打开的文本文件,x、y分别为整型变量。以下语句把x和y两个整型变量中的整数按%d格式输出到fp所指定的文件中:
fprintf(fp, "%d %d", x, y);
注意:为了便于以后读入,两个数之间应该用空格隔开。
以下两条语句等价:
fprintf(stdout, "%d %d", x, y);
printf("%d %d", x, y);
fgets和fputs函数
fgets函数
fgets函数用于从文本文件中读入字符串。
其调用形式如下:
fgets(str, n, fp);
其中fp是文件指针,str是存放字符串的起始地址,n是一个int类型的变量。
函数fgets的功能是从fp所指文件中读入n-1个字符放入以str为起始地址的空间内。
如果在未读满n-1个字符时,读到一个换行符或者EOF,则结束本次读操作,读入的字符串包含最后读到的换行符。
所以,调用fgets函数时,最多只能读入n-1个字符,读入结束后,系统在最后自动加'\0',并以str作为函数值返回。
fputs函数
fputs函数用来把字符串输出到文件中。
其调用形式如下:
fputs(str, fp);
其中fp是文件指针,str是待输出的字符串,可以是字符串常量,指向字符串的指针或存放字符串的字符数组名等。
在用fputs函数输出时,字符串最后的'\0'不输出,也不自动加\n。
输出成果的返回值为正整数,否则为EOF(-1)。
注意:在用fputs函数输出字符串时,文件中各字符串会首尾相接,它们之间不存在任何分隔符。为了方便读入,在输出字符串时,应该人为地加入如“\n"这样的字符串。
fread函数和fwrite函数
fread函数和fwrite函数分别用来读、写二进制文件。
其调用形式如下:
fread(buffer, size, count, fp);
fwrite(buffer, size, count, fp);
其中buffer是数据块的指针,对于fread来说,它是内存块的首地址,输入的数据存入此内存块中。对于fwrite来说,它是准备输出的数据块的地址。
size表示每个数据块的字节数。
count用来指定每读、写一次,输入或输出的数据块的个数(每个数据块具有size字节)。
例如,有如下结构体:
struct st{
char num[8];
float mk[5];
}pers[30];
假设pers数组包含学生的学号和五门课的成绩,并且假设pers数组的30各元素中都已有值,文件指针fp所值文件已经正确打开,则执行以下循环把这30各元素中的数据输出到fp所指文件中去:
for(i = 0; i < 30; i++)
fwrite(&pers[i], sizeof(struct st), 1, fp);
也可以用以下步骤从上面建立的文件中再次将每个学生的数据逐个读入到pers数组中(这时文件必须为读而打开)。
i = 0;
fread(&pers[i], sizeof(struct st), 1, fp);
while(!feof(fp)){
i++;
fread(&pers[i], sizeof(struct st), i, fp);
}
文件定位函数
文件位置指针:表示当前读或写的数据在文件中的位置。
fseek函数
fseek函数用来移动文件位置指针到指定的位置上,接下来的读或写操作将从这个位置开始。
其调用形式如下:
fseek(pf, offset, origin);
这里pf是文件指针,offset是以字节为单位的唯一量,为长整型数,origin是起始点,用以指定位移量是以哪个位置为基准。起始点既可以用数字表示,也可以用标识符来表示。
下表为代表位置指针起始点的标识符和对应的数字:
标识符 | 数字 | 代表的起始点 |
---|---|---|
SEEK_SET | 0 | 文件开始 |
SEEK_END | 2 | 文件末尾 |
SEEK_CUR | 1 | 文件当前位置 |
对于二进制文件,当位移量为正整数时,表示位置指针从指定的起始点向文件尾部方向移动;当位移量为负整数时,表示位置指针从指定的起始点向文件首部方向移动。
假设pf已指向一个二进制文件,以下函数调用将使文件位置指针从文件的开头后移30个字节:
fseek(pf, 30L, SEEK_SET);
对于文本文件,位移量必须是0。
ftell函数
ftell函数用以获得文件当前位置指针的位置,函数给出当前位置指针相对于文件开头的字节数。
若文件指针fp已指向一个正确打开的文件,函数的调用形式如下:
long t;
t = ftell(fp);
当函数调用出错时,函数返回-1L。
ftell函数的使用技巧
当打开一个文件时,可以通过以下函数调用求出文件的字节数:
fseek(fp, 0L, SEEK_END);
t = ftell(fp);
若二进制文件中存放的是struct st类型的结构体类型数据,则通过以下语句可以求出该文件中以该结构体为单位的数据块的个数:
fseek(fp, 0L, SEEK_END);
t = ftell(fp);
n = t / sizeof(struct st);
rewind函数
rewind函数又称”反绕“函数。
其调用形式如下:
rewind(pf);
此处pf为文件指针。
此函数没有返回值,其功能是使文件位置指针回到文件的开头。