目录
一.文件的打开与关闭
(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),则有可能会丢失数据。