一.什么是文件
在程序设计中,一般谈论的文件有两种:程序文件,数据文件。
1.程序文件
包括源程序.c文件,目标文件. obj,可执行程序.exe文件。
本文讨论文件类型是数据文件。
2.数据文件程序设计中,一般谈论的文件有两种:程序文件,数据文件。
文件的内容不一定是程序,而是程序运行时读写的数据。
3.文件名
一个文件要有一个唯一的文件标识,如我们的身份证号一样用于识别。
文件名包含三部分:文件路径+文件名主干+文件后缀
如:c:\code\test.txt
二.文件的打开和关闭
1.文件指针
每个被使用的文件都会在内存中开辟一个相应的文件信息区(如文件名,文件状态以及文件当前位置等)。这些信息保存在一个结构体变量中,该结构体是系统声明的,取名FILE
struct iobuf { char* _ptr; char* _base; int _flag; }; typedef struct iobuf FILE;
每个被使用的文件都自动开辟了FILE类型的结构体变量。
我们一般通过一个FILE的指针对其进行维护。
下面我们创建一个FILE*的指针变量
FILE *pf;//文件指针变量
2.文件的打开和关闭
文件在读写时应先打开,使用完毕后应关闭。
ANSIC规定使用fopen函数打开文件,用fclose函数关闭。
//打开文件 FILE * fopen ( const char * filename, const char * mode ); //关闭文件 int fclose ( FILE * stream );
//代码演示 #include<stdio.h> int main() { FILE* pf; //打开文件 pf = fopen("text.txt", "w"); //文件操作 if (pf != NULL) { fputs("fopen example", pf); //关闭文件 fclose(pf); } return 0; }
三.文件的顺序读写
文件读写函数:
代码实现:
int main() { //打开文件 FILE* pf = fopen("test.txt", "w"); //检验是否打开文件成功 if (NULL == pf) { perror("fopen"); return 1; } //写文件 int i = 0; for (i = 0; i < 26; i++) { fputc('a'+i, pf); } //关闭文件 fclose(pf); pf = NULL; return 0; }
结果演示:
四.文件的随机读写
文件随机读写就是根据文件指针的位置和偏移量来定位文件
1.fseek()函数`int fseek ( FILE * stream, long int offset, int origin );
//test.txt文档内容为26个英文字母 int main() { FILE* ps = fopen("test.txt", "r"); if (ps == NULL) { perror("fopen():"); } int ch = fgetc(ps); printf("%c", ch);//结果 a fseek(ps, 2,SEEK_SET); ch = fgetc(ps); printf("%c", ch);// c fseek(ps, 2, SEEK_CUR); ch = fgetc(ps); printf("%c", ch);// f fseek(ps, -1, SEEK_END); ch = fgetc(ps); printf("%c", ch);// z fclose(ps); ps = NULL; return 0; }
2.ftell()函数
返回文件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
int main() { FILE* ps = fopen("test.txt", "r"); if (ps == NULL) { perror("fopen():"); } int ch = fgetc(ps); printf("%c ", ch); int pos=ftell(ps); printf("%d\n", pos); fseek(ps, 2,SEEK_SET); ch = fgetc(ps); printf("%c ", ch); pos = ftell(ps); printf("%d\n", pos); fseek(ps, 2, SEEK_CUR); ch = fgetc(ps); printf("%c ", ch); pos = ftell(ps); printf("%d\n", pos); fseek(ps, -1, SEEK_END); ch = fgetc(ps); printf("%c ", ch); pos = ftell(ps); printf("%d\n", pos); fclose(ps); ps = NULL; return 0; }
结果可自行对照字母表。
3.rewind()函数
让文件指针的void rewind ( FILE * stream )
int main() { FILE* ps = fopen("test.txt", "r"); if (ps == NULL) { perror("fopen():"); } int ch = fgetc(ps); printf("%c ", ch); int pos = ftell(ps); printf("%d\n", pos); rewind(ps); pos = ftell(ps); printf("%d\n", pos); fclose(ps); ps = NULL; return 0; }
结果演示
五.文件读取结束的判定
1.错误使用的feof
牢记:在文件读取的过程中,不能用feof函数的返回值判断文件是否结束。
而是应用与当文件读取结束时,判断是读取失败结束,还是遇到文件尾结束。
1.文本文件读取是否结束,判断返回值是否为EOF(fgetc()函数),或者为NULL(fgets()函数)
列如:
fgetc()判断是否为EOF;
fgets()的返回值是否为NULL;
2.二进制文件的判断读取结束,判断返回值是否小于要读取的个数
fread()函数判断返回值是否小于实际要求读取的个数
文本文件的例子
#include <stdio.h> #include <stdlib.h> int main(void) { int c; // 注意:int,非char,要求处理EOF FILE* fp = fopen("test.txt", "r"); if(!fp) { perror("File opening failed"); return EXIT_FAILURE; } //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环 { putchar(c); } //判断是什么原因结束的 if (ferror(fp)) puts("I/O error when reading"); else if (feof(fp)) puts("End of file reached successfully"); fclose(fp) }