引言:如果没有文件我们写的程序的数据是存在电脑的内存中,如果程序退出,内存回收,数据就丢失了,想使数据进行持久化的保存,我们可以使用文件。
数据的组织形式,数据文件被称为文本文件或二进制文件。
流:可以被想象成流淌着字符的河。c程序对文件、画面、键盘等的数据输入输出都是通过流操作来完成的。
一、文件指针:
FILE* pf
定义一个指向FILE类型数据的指针变量,可以使pf指向某个文件的文件信息区(是一个结构体变量),通过文件信息区中的信息就能够访问该文件。【通过文件信息区中的信息就能够访问该文件】
1、打开文件:fopen
mode:打开文件模式(方式)
2、关闭文件
关闭后还需要将文件置空。
打开或关闭文件的模式(方式)
“r”(只读):为了输入数据,打开一个已经存在的文本文件。如果指定文件不存在,就会出错。
“w”(只写):为了输出数据,打开一个文本文件,如果指定文件不存在就会建立一个新文件。(如果已经有内容,就会清空已有内容)
“a”(追加):向文本文件中添加数据,会建立一个新的文件
“rb”(只读):打开一个二进制文件;如果指定文件不存在,就会出错。
“wb”(只写):为了输出,打开二进制文件;如果指定文件不存在就会建立一个新文件。
“ab”(追加):向二进制文件尾部添加数据,如果指定文件不存在就会建立一个新文件。
“r+”(读写):打开一个文本文件,如果指定文件不存在,就会出错。
“w+”(读和写):打开文本文件,建立一个新文件
“a+”,为了读写,打开一个文件,在文件尾部进行读写;建立新文件
“rb+”为了读写,打开二进制文件,如果指定文件不存在,就会出错。
“wb+”为了读写,新建一个二进制文件,建立一个新文件。
“ab+”(读和写),打开二进制文件,在文件尾部进行读和写;如果指定文件不存在就会建立一个新文件。
二、文件的顺序读写
1、fgetc
int main()
{
FILE* pf;
pf= fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "r");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
fgetc(pf);
fclose(pf);
return 0;
}
2、fputc
int main()
{
FILE* pf;
pf= fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "w");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
int a= fputc(66,pf);
fclose(pf);
return 0;
}
结果为:
3、fgets
int main()
{
FILE* pf;
pf= fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "r");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
char arr[100];
while (fgets(arr, sizeof(arr), pf) != NULL)
{
printf("%s", arr);
}
fclose(pf);
return 0;
}
原来文本文件内容是:
从文本文件中读取数据结果为:
4、fputs
int main()
{
FILE* pf;
pf= fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "w");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
char arr[100]="abcdefgh";
fputs(arr, pf);
fclose(pf);
return 0;
}
输出到文件中结果为:
5、fscanf函数
从文件读取格式化数据的函数。
int main()
{
FILE* pf;
pf= fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "r");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
int num;
float f;
char str[20];
fscanf(pf, "%d %f %s", &num,&f, str);
printf("%d\n",num);
printf("%f\n", f);
printf("%s\n", str);
fclose(pf);
return 0;
}
6、fprintf函数
用于向文件中写入格式化的数据。
int main()
{
FILE* pf;
pf= fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "w");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
int num=980;
float f=3.141592;
char str[20]="abcdefghijk";
fprintf(pf,"%d %f %s", num, f, str);
fclose(pf);
return 0;
}
7、fread函数
int main()
{
FILE* pf;
pf = fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "rb");
if (pf == NULL)
{
perror("fopen failed");
return 1;
}
int num2[100] = {0};
fread(&num2, sizeof(int), 1, pf);
printf("%d", num2[0]);
fclose(pf);
return 0;
}
8、fwrite
int main() {
FILE* pf;
pf = fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "rb");
if (pf == NULL) {
perror("fopen for reading failed");
return 1;
}
int read_num2[6];
size_t read_count = fread(read_num2, sizeof(int), 6, pf);
if (read_count != 6) {
fprintf(stderr, "fread failed, only read %zu elements\n", read_count);
fclose(pf);
return 1;
}
for (int i = 0; i < 6; i++) {
printf("%d ", read_num2[i]);
}
printf("\n");
if (fclose(pf) != 0) {
perror("fclose failed");
return 1;
}
return 0;
}
9、函数对比
(1)scanf和printf、(2)fscanf和fprintf、(3)sscanf和sprintf函数
(1)scanf函数/printf函数针对标准输入/输出的格式化数入/输出函数
(2)fscanf/fprintf函数针对所有文件流和标准输入输出流的输入/输出函数
(3)sscanf/sprintf函数:
sscanf函数是从字符串中读取格式化的数据(将字符串转化为格式化数据)
sprintf函数是从字符串中读取格式化的数据(格式化数据写到字符串中)
三、文件随机读写
1、fseek
intoffset--->偏移量 ; origin---->起始位置(有三种类型:(1)SEEK_SET Begining of file
(2)SEEK_CUR CURRENT position of the file pointer 文件指针当前的位置(3)SEEK_END End of file* 文件末尾)
2、ftell函数(返回文件指针相对于起始位置偏移量)
int main() {
FILE* pf;
pf = fopen("C:\\Users\\test\\平时博客代码书写\\test.txt", "rb");
if (pf == NULL) {
perror("fopen for reading failed");
return 1;
}
fseek(pf, 0, SEEK_END);
long filesize = ftell(pf);
printf("%d ", filesize);
if (fclose(pf) != 0) {
perror("fclose failed");
return 1;
}
return 0;
}
3、rewind函数
让文件指针的位置回到文件的起始位置
四、文件操作
1、feof
在文件读取过程中,不能用feof的返回值来判断文件读取是否结束。
读取结束有俩种可能性:遇到文件末尾;读取遇到错误失败
feof函数用来判断是不是因为遇到文件末尾而结束
ferror函数是用来判断:文件读取是不是遇到了错误而结束。
2、注
1、文本文件读取是否结束,判断返回值是否为EOF,或NULL;fgets判断返回值是否为NULL
fgetc判断是否为EOF.
2、二进制文件的读取结束判断:判断返回值是否小于实际要读的个数;例如:fread函数判断返回值是否小于实际要读的个数。