文件类型
数据文件分为文本文件和二进制文件。
数据在内存中以二进制的形式存储,如果不加以转换的输出到外存,就是二进制文件。
以ASCII字符的形式存储的文件就是文本文件。
123456789 | int main() { int a = 10000; FILE* pf = fopen("test.txt", "wb");//wb的意思是以二进制的形式写文件text.txt fwrite(&a, 4, 1, pf); fclose(pf); pf = NULL; return 0;} |
文件指针
一般通过FILE的指针来维护这个FILE结构的变量。
文件指针变量:FILE* pf
文件打开关闭
文件在读写之前先打开文件,在使用结束之后关闭文件。
在编写程序时,在打开文件的同时,会返回一个FILE*类型的指针变量指向该文件。
用fopen打开文件,用fclose关闭文件。FILE* fopen (const char *filename, const char* mode);int fclose (FILE* stream);
文件打开方式:
| 文件使用方式 | 含义 | 如果指定文件不存在 |
|---|---|---|
| “r”(只读) | 为了输入文件,打开一个已经存在的文本文件 | 出错 |
| “w”(只写) | 为了输出数据,打开一个文本文件 | 建立新文件 |
| “a”(追加) | 向文本末尾添加数据 | 出错 |
| “rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
| “wb”(只写) | 为了输出数据,打开一个二进制文件 | 建立新文件 |
| “ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
| “r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
| “w+”(读写) | 为了读和写,建立一个新文件 | 建立新文件 |
| “a+”(读写) | 打开一个文件,在文件尾读写 | 建立新文件 |
| “rb+”(读写) | 为了读和写,打开一个二进制文件 | 出错 |
| “wb+”(读写) | 为了读和写,新建一个二进制文件 | 建立新文件 |
| “ab+”(读写) | 打开一个二进制文件,在文件尾进行读写 | 建立新文件 |
12345678910111213141516171819 | int main(){ //打开文件text.txt FILE* pf = fopen("test.txt", "w"); if (pf == NULL)//打开失败 { printf("%s\n",strerror(errno)); return 0; } //打开成功 //读文件 //关闭文件 fclose(pf); pf = NULL; return 0;} |
文件的顺序读写
| 功能 | 函数名 | 适用于 |
|---|---|---|
| 字符输入函数 | fgetc | 所有输入流 |
| 字符输出函数 | fputc | 所有输出流 |
| 文本行输入函数 | fgets | 所有输入流 |
| 文本行输出函数 | fputs | 所有输出流 |
| 格式化输入函数 | fscanf | 所有输入流 |
| 格式化输出函数 | fprintf | 所有输出流 |
| 二进制输入 | fread | 文件 |
| 二进制输出 | fwrite | 文件 |
fputc
字符输出。int fputc ( int character, FILE * stream );
123456789101112131415161718192021 | int main(){ FILE* pfWrite = fopen("test.txt", "w"); if (pfWrite == NULL) { printf("%s\n",strerror(errno)); return 0; } //写文件 fputc('H', pfWrite); fputc('e', pfWrite); fputc('l', pfWrite); fputc('l', pfWrite); fputc('o', pfWrite); //关闭文件 fclose(pfWrite); pfWrite = NULL; return 0;} |
程序运行后,test.txt内容改为Hello。先前的内容被抹去。fputc一次会写入一个字符。
fgetc
字符输入。int fgetc ( FILE * stream );
123456789101112131415161718192021 | int main(){ FILE* pfRead = fopen("test.txt", "r"); if (pfRead == NULL) { printf("%s\n",strerror(errno)); return 0; } //读文件 printf("%c",fgetc(pfRead));//H printf("%c",fgetc(pfRead));//e printf("%c",fgetc(pfRead));//l printf("%c",fgetc(pfRead));//l printf("%c",fgetc(pfRead));//0 //关闭文件 fclose(pfRead); pfRead = NULL; return 0;} |
fgetc一次读一个字符。
test.txt的内容是:Hello
fgets
文本行输入。char * fgets ( char * str, int num, FILE * stream );
12345678910111213141516171819202122 | int main(){ char buf[1024] = {1}; FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { printf("%s\n",strerror(errno)); return 0; } //读文件 fgets(buf,1024,pf);//fgets会读取到最后的换行符,所以打印时不用加\n就会换行,加了\n就换两行 printf("%s",buf);//Hello fgets(buf,1024,pf); printf("%s",buf);//World //关闭文件 fclose(pf); pf = NULL; return 0;} |
text.txt原先的内容是:
12 | HelloWorld |
一个fgets会读取一行文本至最后,fgets会读取到最后的换行符,所以打印时不用加\n就会换行,加了\n就换两行。
想要读取两行文本,就用两个fgets。
fputs
文本行输出。int fputs(const char *string,FILE *stream);
12345678910111213141516171819 | int main(){ char buf[1024] = {0}; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { printf("%s\n",strerror(errno)); return 0; } //写文件 fputs("hello\n", pf); fputs("world", pf); //关闭文件 fclose(pf); pf = NULL; return 0;} |
运行程序后,test.txt的内容为:
12 | helloworld |
使用fputs函数,想在文件中换行需要自己输入\n。
12345678910 | int main(){ char buf[1024] = {0}; fgets(buf,1024,stdin);//从标准输入流读取信息(键盘) fputs(buf, stdout);//输出到标准输出流(屏幕) return 0;} |
fscanf
格式化的输入数据。int fscnaf(FILE *stream,const char *format[,arguments]...);
1234567891011121314151617181920212223 | struct S{ int n; float f; char arr[10];};int main(){ struct S s = {0}; FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } //以格式化输入数据 fscanf(pf, "%d %f %s",&(s.n),&(s.f),&(s.arr)); printf("%d %f %s\n",s.n,s.f,s.arr); fclose(pf); pf = NULL; return 0;} |
test.txt的内容是:100 3.140000 Hello
程序运行后,屏幕上输出:100 3.140000 Hello
123456789101112131415 | struct S{ int n; float f; char arr[10];};int main(){ struct S s ={ 0 }; fscanf(stdin, "%d %f %s",&(s.n),&(s.f),&(s.arr));//从标准输入流获取数据(键盘) fprintf(stdout, "%d %f %s",s.n,s.f,s.arr);//从标准输出流输出数据(屏幕)} |
fprintf
以格式化的形式写文件。int fprintf ( FILE * stream, const char * format, ... );
1234567891011121314151617181920212223 | struct S{ int n; float f; char arr[10];};int main(){ struct S s = {100,3.14,"Hello"}; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { return 0; } //以格式化的形式写文件 fprintf(pf, "%d %f %s",s.n,s.f,s.arr); fclose(pf); pf = NULL; return 0;} |
程序运行后,test.txt被改为:100 3.140000 Hello
fread
以二进制的形式读文件。size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
1234567891011121314151617181920212223 | struct S{ char name[20]; int age; double score;};int main(){ struct S s ={ 0 }; FILE* pf = fopen("test.txt", "rb"); if (pf == NULL) { return 0; } //二进制形式读文件 fread(&s, sizeof(struct S), 1, pf); printf("%s %d %lf\n",s.name,s.age,s.score); fclose(pf); pf = NULL; return 0;} |
test.txt的内容为张三 12 111.999000
输出的结果是张三 12 111.999000
fwirte
以二进制的形式写文件。size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
1234567891011121314151617181920212223 | struct S{ char name[20]; int age; double score;};int main(){ struct S s = {"张三",12,111.999}; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { return 0; } //二进制形式写文件 fwrite(&s, sizeof(struct S), 1, pf); fclose(pf); pf = NULL; return 0;} |
程序运行后,test.txt的内容被改为张三 12 111.999000
文件的随机读写
fseek
根据文件指针的位置和偏移量来定位文件指针。int fseek (FILE* stream , long int offset , int origin );long int offset是偏移量,int origin是文件指针的当前位置。
test.txt文件的内容是abcdef
123456789101112131415161718 | int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } //1、定位文件指针 fseek(pf, 1, SEEK_CUR); //2、读取文件 int ch = fgetc(pf); printf("%c\n",ch);//b fclose(pf); pf = NULL;} |
ftell
返回文件指针相对于起始位置的偏移量。long int ftell (FILE *stream);
12345678910111213141516 | int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } fgetc(pf); //读取文件 int pos = ftell(pf); printf("%d\n",pos); fclose(pf); pf = NULL;} |
打印的结果是1
rewind
让文件指针位置回到文件的起始位置void rewind (FILE* stream);
test.txt文件的内容是abcdef
123456789101112131415161718 | int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } int ch = fgetc(pf);//读取的结果是a printf("%c ",ch); //2、读取文件 rewind(pf); ch = fgetc(pf);//还是a printf("%c ",ch); fclose(pf); pf = NULL;} |
文件结束的判定
被错误使用的feof
在文件读取的过程中,不能用feof的返回值判断文件是否读取结束。
这个函数是用于当文件读取结束时,判断时读取失败结束,还是遇到文件尾结束。
test.txt文件的内容是abcdef
12345678910111213141516171819202122232425 | int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("open file test.txt"); return 0; } int ch = 0; while ((ch = fgetc(pf)) != EOF) { putchar(ch); } if (ferror(pf)) { printf("error\n"); } else if (feof(pf)) { printf("end of file\n"); } fclose(pf); pf = NULL;} |
打印的结果是abcdefend of file