一.文件的打开与关闭
(1)代码演示
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("contact.dat", "r"); if (pf == NULL)// 打开哪个文件 什么形式打开 { perror("fopen:"); //如果打开失败返回空指针 return 1; //报错退出 } //操作文件 //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(2)关于fopen 文件的打开方式
“r”只读 文件必须存在
“w”只写 文件如果存在 会销毁掉之前内容 文件如果不存在 会新建一个空文件
“a”追加 在文本文件末尾添加数据
“rb”只读 以二进制的形式读取文件
“wb”只写 以二进制的形式写进文件
“ab”二进制的追加
二.操作文件函数
1.文件顺序读写
(1)fputc
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "w"); if (pf == NULL) // 写 { perror("fopen:"); return 1; } //写文件 fputc('a', pf); fputc('b', pf); fputc('c', pf); // 要写的字符 写到哪里去 //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(2)fgetc
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "r"); if (pf == NULL) // 读 { perror("fopen:"); return 1; } //读文件 int ch = 0; while ((ch = fgetc(pf)) != EOF) //读取哪个文件 { printf("%c", ch); } //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(3)fputs
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "w"); if (pf == NULL) // 写 { perror("fopen:"); return 1; } //写文件 - 写一行 fputs("abcdefghk\n", pf); fputs("xxxxxxxxx\n", pf); //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(4)fgets
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "r"); if (pf == NULL) // 读 { perror("fopen:"); return 1; } //读文件 - 读一行 char arr[256] = { 0 }; //fgets(arr, 256, pf); // 读出来放到哪里 一行最多读几个 从哪个文件读 while ((fgets(arr, 256, pf) != NULL)) { printf("%s", arr); } //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(5)fprintf
#include<stdio.h> struct S { char name[20]; int age; double d; }; int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "w"); if (pf == NULL) // 写 { perror("fopen:"); return 1; } //以格式化的形式向文件输入数据 struct S s = { "zhangsan",18,95.5 }; //正常printf一个结构体 //printf("%s %d %lf", s.name, s.age, s.d); fprintf(pf, "%s %d %lf", s.name, s.age, s.d); // 只是多了一个输出到哪里去pf //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(6)fscanf
#include<stdio.h> struct S { char name[20]; int age; double d; }; int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "r"); if (pf == NULL) // 读 { perror("fopen:"); return 1; } //以格式化的形式向文件输入数据 struct S s = { 0 }; //正常scanf一个结构体 //scanf("%s %d %lf", s.name, &(s.age), &(s.d)); fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d)); // 只是多了一个从哪里来的数据pf fprintf(stdout, "%s %d %lf", s.name, s.age, s.d); //打印到屏幕上 //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(7)fwrite
#include<stdio.h> struct S { char name[20]; int age; double d; }; int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "wb"); if (pf == NULL) //以二进制写 { perror("fopen:"); return 1; } //以二进制形式向文件输入数据 struct S s = { "张三",18,99.5 }; fwrite(&s, sizeof(struct S), 1, pf); //从哪里来得数据 一个多大 要输入几个 输入到哪里去 //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(8)fread
#include<stdio.h> struct S { char name[20]; int age; double d; }; int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "rb"); if (pf == NULL) // 以二进制读 { perror("fopen:"); return 1; } //以二进制形式读文件 struct S s = { 0 }; fread(&s, sizeof(struct S), 1, pf); printf("%s %d %lf\n", s.name, s.age, s.d); //读完放到哪里 一个多大 要读几个 从哪里读 //fread 与 fwrite很像 //fwrite(&s, sizeof(struct S), 1, pf); //从哪里来得数据 一个多大 要输入几个 输入到哪里去 //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
2.文件随机读写
(1)fseek随机读文件
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "r"); if (pf == NULL) // 读 { perror("fopen:"); return 1; } //随机读文件 //SEEK_CUR - 文件指针当前的位置 //SEEK_END - 文件末尾的位置 //SEEK_SET - 文件开始的位置 int ch = 0; fseek(pf, 2, SEEK_CUR); //操作pf 从指针当前位置向右偏移2位 ch = fgetc(pf); printf("%c\n", ch); //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
(2)fseek随机写文件
#include<stdio.h> int main() { //打开和操作文件 FILE* pf = fopen("test.txt", "w"); if (pf == NULL) // 写 { perror("fopen:"); return 1; } //随机写文件 fputc('a', pf); fputc('b', pf); fputc('c', pf); fputc('d', pf); fseek(pf, -2, SEEK_CUR); fputc('w', pf); //关闭文件 fclose(pf); pf = NULL;//防止野指针 return 0; }
拓展:ftell — 返回文件指针相对于起始位置的偏移量
rewind —让文件指针回到文件起始的位置
二.文本文件与二进制文件
二进制文件:数据在内存中以二进制的形式储存,如果不加以转换的输出到外存,就是二进制文件
文本文件:如果要求外存上以ASCII的形式存储,则需要在储存前转换,是以ASCII形式存储的文件
例如:
整数10000 既可以以文本文件存储,也可以以二进制形式存储。文本类型存储,将10000看做1 0 0 0 0 五个字符。所占内存为5个字节(5个char)。而二进制存储,10000就是一个int类型,大小为4个字节。
三.文件读取结束的判定
1.被错误使用的feof
概念:feof函数不是用来判断文件是否读取结束。而是在文件读取结束后,来判断结束原因的。
是判断文件是读取失败结束,还是读到文件末尾结束的。
(1)文本文件判断是否读取结束
1.fgetc判断是否为EOF
2.fgets返回的是指针 所以我们判断是否为NULL
(2)二进制文件判断是否读取结束
1.fread的参数count 是最大要读取的个数 而fread返回的是实际读取的个数。
所以fread判断返回值是否小于要读取的个数
四.文件缓冲区
1.概念:文件缓冲区是内存开辟的一块空间。目的是当文件操作攒够一定数量再一起传给程序数据或硬盘。由此来提升效率。
2.fflush函数用来手动刷新缓冲区,即将存放在缓冲区里的数据传出。
3.fclose有刷新缓冲区的作用,即将存放在缓冲区里的数据传出。所以如果文件操作没有关闭文件(fclose),则有可能会丢失数据。