操作系统把各种设备都统一作为文件处理。文件一般指在外部介质上数据的集合。
C语言把文件看作是一个字符或字节的序列,即由一个一个字符或字节的数据顺序组成;C的数据文件由一连串的字符或字节组成,而不考虑行的界限,两行数据间不会自动加分隔符,对文件的存取是以字符或字节为单位的。输入输出数据流的开始和结束仅受程序控制而不受物理符号(如回车)的控制,增加了处理的灵活性;称为流式文件。
文件缓冲区。ANSI C标准采用“缓冲文件系统”处理数据文件,指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区,用来存放输入输出数据;从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘。输入缓冲区,输出缓冲区。
文件类型指针。文件指针,每个被使用的文件在内存中开辟一个相应的文件信息区,用来存放文件的有关信息(文件名,状态,当前位置等)。FILE,stdio.h中声明;文件的指针变量,指向内存中文件信息区的开头;不同的编译系统FILE的定义不同。
文件的打开和关闭。文件的打开,指为文件建立相应的信息区和文件缓冲区;文件的关闭,指撤销文件信息区和缓冲区,是文件指针变量不再指向该文件。
fopen(文件名,使用文件方式);返回一个文件的指针变量,出错则返回NULL空指针;这里的输入输出都是指输入计算机,从计算机输出;这里的文件名指的是,文件路径,文件名,后缀的组合;如果没有路径,默认指当前路径;此路径中可以使用“.”或“..”不能使用“~”。
// 将在e盘根目录下新建test.txt文件
fopen("e:\\test\\..\\test.txt"."w");
文件只用方式 | 含义 | 如果指定文件不存在 |
r --- 只读 | 为了输入数据,打开一个已存在的文本文件,只用来向计算机输出 | 出错 |
w --- 只写 | 为了输出数据,打开一个文本文件,只用来向文件写数据 | 建立新文件 |
a --- 追加 | 向文本文件尾添加数据,打开时,文件的读写位置标记移到文件末尾 | 出错 |
rb --- 只读 | 为了输入数据,打开一个二进制文件 | 出错 |
wb --- 只写 | 为了输出数据,打开一个二进制文件 | 建立新文件 |
ab --- 追加 | 向二进制文件尾添加数据 | 出错 |
r+ --- 读写 | 为了读和写,打开一个文本文件,RW | 出错 |
w+ --- 读写 | 为了读和写,建立一个新的文本文件,RW | 建立新文件 |
a+ --- 读写 | 为了读和写,打开一个文本文件,RW | 出错 |
rb+ --- 读写 | 为了读和写,打开一个二进制文件 | 出错 |
wb+ --- 读写 | 为了读和写,建立一个新的二进制文件 | 建立新文件 |
ab+ --- 读写 | 为了读写打开一个二进制文件 | 出错 |
#include<stdlib.h>
if((fp=fopen("file1","r"))==NULL){
printf("open error\n");
exit(0);
}
每个数据文件中定义一个隐式的“文件读写位置标记”,它指向的位置就是当前进行读写的位置;
计算机从ASCII文件读入字符时,遇到回车换行符,系统把他转换为一个换行符;在输出到文件时,把换行符转换成回车和换行两个字符。应该就是window和linux换行符不同的原因;可以手动写程序读文件中的回车并打印,返回的确实为10 即换行符;
fclose(文件指针);关闭文件时,有些编译系统会自动先将缓冲区中的数据写到文件中,但是应养成在程序终止前关闭所有文件的习惯;关闭成功返回0,关闭失败返回EOF(-1);
顺序读写数据文件:
1. 文本文件:
fgetc(fp);从fp指向的文件读入一个字符,读成功,返回所读字符;失败则返回文件结束标志EOF;
fputc(ch,fp);把ch写到fp多指文件中,成功则返回输出字符;失败则返回EOF;
fgets(str,n,fp);从文件读入一个长度为n-1的字符串,并且末尾加一个'\0'字符;最后把n个字符放到数组str里面;成功则返回str地址,失败返回NULL;如果遇到换行符\n和EOF,读入结束,而且\n也作为字符被读入;
fputs(str,fp);把str指向的字符串写入文件中,结尾的'\0'不写入,成功返回0,失败返回非零;字符串末尾的\0不输出;
fprintf(文件指针,格式字符串,输出列表);
fscanf(文件指针,格式字符串,输入列表);
2. 二进制文件:
fread(buffer,size,count,fp);从文件读入到内存中;
fwrite(buffer,size,count,fp);buffer为读入和写入的地址,size为每个数据项长度字节,count为多少个size;
随机读写数据文件:
文件位置标示,指示接下来要读写的下一个字符的位置;读操作,位置指向第一个;写操作,位置指向最后一个的后面;
rewind(fp);是文件位置标记指向文件头;
fseek(文件指针,位移量,起始点);位移量应是long型;以起始点为基点,向前移动的字节数;
位移量为正数,向文件尾偏移;负数,向文件头偏移;
起始点 | 名字 | 数字表示 |
文件的开始位置 | SEEK_SET | 0 |
文件的当前位置 | SEEK_CUR | 1 |
文件的末尾位置 | SEEK_END | 2 |
ftell(fp);测定文件位置标记的当前位置;返回相对文件开头的偏移量。出错返回-1L;刚打开的文件,返回值为0;
文件读写的出错检测:
ferror(fp);除了通过文件函数的返回值反映,还可通过ferror()函数检查;返回0表示未出错;返回1表示出错;
clearerr(fp);是文件错误标志和问津结束标志置0。如果ferror()返回非0,应立即调用clearerr(fp),使ferror(fp)的返回值变为0,比便下一次检查;只要出现文件读写错误标志,他就一直保留,知道对同一文件调用clearerr()或rewind,或任何其他一个输入输出函数;
文件结束符:
1. feof(fp);检测流文件的文件结束符;当读取完最后一个字节的数据后,文件结束标志并没有被置位,只有当位置指针到达末尾时,再发生读取操作时(即feop()返回的是上一次读取的状态),而此时又没有数据可供读取,则返回1,此时文件结束标志被置位;文件没有结束时,返回0。EOF可以判断文本文件,但不能判断二进制文件;feof(fp),可同时判断。注意网上参考feof()的英文描述。
int ch;
FILE *fp;
/*假设*fp所指文件内容为"abcd"*/
while(!feof(fp)){
printf("%d\n",fgetc(fp));
}
则结果应该是:
a
b
c
d
-1
2. EOF: 在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~255,不可能出现-1,因此可以用EOF作为文件结束标志。读文件如果返回0xFF或EOF说明到达了结尾;需要再读一次,feof才置位结束标志位,返回才为真
C语言中,当把数据以二进制形式存放到文件中时,就会有-1值的出现,此时不能采用EOF作为二进制文件的结束标志。为解决这个问题,ANSI C提供一个feof函数,用来判断文件是否结束。如果遇到文件结束,函数feof(fp)的值为1,否则为0. feof函数既可用以判断二进制文件是否结束,也可以用以判断文本文件是否结束。
linux下EOF在以下情况为结束符,其余为换行符:
1. 第一个字符为ctrl+d
2. 前一个输入字符为换行符,接着输入ctrl+d
3. 前面有字符输入,切不为换行符,输入两次ctrl+d,第一个起到开始读取缓冲区数据作用;第二个起到文件结束符;
window下使用ctrl+z表示结束符;此时ctrl+d ASCII码为0x04;
注意:
1. linux下的换行符为 \n,而DOS下为\r\n,所以window和linux文件共享时,注意格式的转换;
2. 输入是按照文件进行读取的,文件中一般都是以行为单位的。因此,只有遇到换行符,那么程序会认为输入结束,然后采取执行程序的其他部分。要结束一个文件的输入就需用到EOF (Enf Of File).。