🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记
🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
🔥引言
本章将介绍文件读取函数的相关知识和展示使用场景,通过这些函数就可以打开文件与我们之间的桥梁。
如果需要对文件进行一些读写操作,那么首先就需要先打开文件,在使用完以后关闭文件,所以最基本是打开文件和关闭文件。
ANSIC规定使用fopen函数来打开文件,fclose来关闭文件
打开文件 FILE *fopen(const char *filename,const char *mode); 关闭文件 FILE *fclose(FILE *stream);
mode表示文件的打开模式,下面都是文件的打开模式 :
⽂件使⽤⽅式 | 含义 | 如果指定⽂件不存在 | |||
---|---|---|---|---|---|
“r”(只读) | 为了输⼊数据,打开⼀个已经存在的⽂本⽂件 | 出错 | |||
“w”(只写) | 为了输出数据,打开⼀个⽂本⽂件 | 建⽴⼀个新的⽂件 | |||
“a”(追加) | 向⽂本⽂件尾添加数据 | 建⽴⼀个新的⽂件 | |||
“rb”(只读) | 为了输⼊数据,打开⼀个⼆进制⽂件 | 出错 | |||
“wb”(只写) | 为了输出数据,打开⼀个⼆进制⽂件 | 建⽴⼀个新的⽂件 | |||
“ab”(追加) | 向⼀个⼆进制⽂件尾添加数据 | 建⽴⼀个新的⽂件 | |||
“r+”(读写) | 为了读和写,打开⼀个⽂本⽂件 | 出错 | |||
“w+”(读写) | 为了读和写,建议⼀个新的⽂件 | 建⽴⼀个新的⽂件 | |||
“a+”(读写) | 打开⼀个⽂件,在⽂件尾进⾏读写 | 建⽴⼀个新的⽂件 | |||
“rb+”(读写) | 为了读和写打开⼀个⼆进制⽂件 | 出错 | |||
“wb+”(读写) | 为了读和写,新建⼀个新的⼆进制⽂件 | 建⽴⼀个新的⽂件 | |||
“ab+”(读写) | 打开⼀个⼆进制⽂件,在⽂件尾进⾏读和写 | 建⽴⼀个新的⽂件 |
在打开和关闭文件一般直接输入指定的文件名,当然也可以根据文件的路径对该文件进行操作。
路径分为:
对此当前文件test1.txt在D:\code\2024\2024\Document(绝对路径) FILE* pf = fopen("C:\\Users\\zpeng\\Desktop\\test.txt", "w"); 当test1.txt在其他文件夹中,可以通过上面表示的关系寻找 FILE* pf = fopen(".\\..\\..\\hehe\\test.txt", "w");
FILE *fopen(const char * filename, const char * mode)
【说明】:
FILE指针
进行标识。int fclose(FLIE *stream)
【说明】:
这里所有的输入流、输出流分别指stdin(标准输入流)、stdout(标准输出流)和文件流
【函数部分说明】:
功能上:
将字符写入流并推进位置指示器,然后自动前进1。适用于所有输入流(字符输入到流中)
参数部分上:
character:
stream:
返回值:
int main() { FILE* pf = fopen("test1.txt", "w"); if (pf == NULL) { perror("fopen fail!!!"); return; } fputc('d', pf); fputc('e', pf); fclose(pf); pf = NULL; return 0; }
【使用说明】:
【练习】:使用fputc将A ~Z个字符输入到指定文件和显示器中
int main() { FILE* pf = fopen("test1.txt", "w"); if (pf == NULL) { perror("fopen fail!!!"); return; } for (char i = 'A'; i <= 'Z'; i++) { fputc(i, pf);//输入到文件中 fputc(i, stdout);//输入到显示器中 } fclose(pf); pf = NULL; return 0; }
【函数部分说明】:
int main() { FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen fail!!!"); return; } char ch; //ch用于接收fgetc从流中获得的字符 ch = fgetc(pf); printf("%c", ch); ch = fgetc(pf); printf("%c", ch); fclose(pf); pf = NULL; return 0; }
【使用说明】:
ch = fgetc(stdin);
通过以上两个函数,我们可以用来实现文件拷贝的场景
int main() { FILE* pfread = fopen("data1.txt", "r"); if (pfread == NULL) { perror("fopen fail!!!"); return; } FILE* pfwrite = fopen("data2.txt", "w"); if (pfwrite == NULL) { fclose(pfread);//读文件操作没有必要 pfread=NULL; perror("fopen fail!!!"); return; } char ch; while ((ch = fgetc(pfread)) != EOF) { fputc(ch, pfwrite); } fclose(pfread); fclose(pfwrite); return 0; }
【使用说明】:
data1.txt
中提前输入数据data1.txt
使用读的形式,而data2.txt
是写的形式打开data1.txt
读取字符,同时一个向data2.txt
输入字符,直到读取完成或者发生错误【函数部分说明】:
int main() { FILE * pf = fopen("test1.txt", "w"); if (pf == NULL) { perror("fopen fail!!!"); return; } //fputs("hellow world", pf); -- 将字符串输入到文件流中 fputs("hellow world", stdout); -- 将字符串输入到输出流中(打印到屏幕上) fclose(pf); pf=NULL; return 0; }
【函数部分说明】:
功能上:
num-1
个字符或者在达到换行符或文件末尾(前者为准)
。fgets
停止,但函数将其视为有效字符,并包含在复制到str
的字符串中,在将字符复制到str
之后,会自动添加\0
,导致只能读取num-1
字符参数部分上:
str:
num:
返回值:
EOF
int main() { FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen fail!!!"); return; } char ch[1000]="xxxxxxx"; fgets(ch, 7, pf); printf("%s", ch); fclose(pf); pf = NULL; return 0; }
【说明】:给\0留了一个位置
fprint
和fscanf
属于格式化输入输出函数,将不同数据类型放在结构体中进行统一管理。
struct S { char a[1000]; int p; float pa; };
【函数部分说明】:
功能上:
text1.txt
中去。返回值:
int main() { struct S s={"zhangsan",100,4.3}; FILE* pf = fopen("test1.txt", "w"); if (pf == NULL) { perror("fopen fail!!!"); return; } fprintf(pf,"%s %d %f", s.a, s.p, s.pa); fclose(pf); pf = NULL; return 0; }
【函数部分说明】:
功能:
text1.txt
对应的数据,输入到对应的数据变量中返回值:
成功后,该函数返回已成功填充的参数列表的项数,失败,EOF
int main() { struct S s;//这里没有初始化,目的是通过fscanf赋值 FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen fail!!!"); return; } fscanf(pf, "%s %d %f", s.a, &(s.p), &(s.pa)); printf("%s %d %f", s.a, s.p, s.pa); fclose(pf); pf = NULL; return 0; }
【函数部分说明】:
功能:
从字符串中读取格式化数据(将字符数组中的字符串按照格式说明符转换为对应的格式化数据)
【函数部分说明】:
功能:
将格式化数据写入字符串(格式化数据转换为字符串存放在字符数组中)
基于以上两个函数使用场景:
int main() { //将格式化的数据转换为字符串存放在p数组中 struct S s = { "zhangsan",100,4.3 }; char p[1000] = { 0 }; sprintf(p, "%s %d %f", s.a, s.p, s.pa); printf("%s\n", p); //从p这个字符串中提取格式化的数据(用p数组中的数据,为结构体t成员赋值) struct S t; sscanf(p, "%s %d %f", t.a, &(t.p), &(t.pa)); printf("%s %d %lf", s.a, s.p, s.pa); return 0; }
在这里插入图片描述
【函数部分说明】:
功能:
返回值:
int main() { FILE* pf = fopen("test1.txt", "wb");//打开一个二级制文件 if (pf == NULL) { perror("fopen fail!!!"); return; } int nums[] = { 1,2,3,4,5,6,7 }; fwrite(nums, sizeof(int), 7, pf); fclose(pf); pf = NULL; return 0; }
【注意】:这里是通过二进制的形式写入文本文件中,如果想要看懂输入的数据,可以在打开方式选择二进制编辑器或者使用fread函数读取出来
【函数部分说明】:
返回值:
比如:如果实际文件中只有7个字符,count是14,那么读到7给字符就结束(返回值 < count就返回)
int main() { FILE* pf = fopen("test1.txt", "rb");//打开一个二级制文件 if (pf == NULL) { perror("fopen fail!!!"); return; } //int nums[] = { 1,2,3,4,5,6,7 }; //fwrite(nums, sizeof(int), 7, pf); //读取二进制存放的信息 int nums[10] = { 0 }; fread(nums, sizeof(int), 10, pf); for (int i = 0; i < 10; i++) { printf("%d ", nums[i]); } fclose(pf); pf = NULL; return 0; }
由于文本文件和二进制文件使用方面存在差异,下面三个函数将采用二进制文件
【函数部分说明】:
功能上:
返回值:
【注意】:
【原点】
特别注意的是起源(从哪个位置),用作偏移参考位置
int main() { FILE* pf = fopen("test1.txt", "wb");//打开一个二级制文件 if (pf == NULL) { perror("fopen fail!!!"); return; } fputs("This is an apple", pf); fseek(pf, 3, SEEK_SET); fputs("sam", pf); fseek(pf, -3, SEEK_END);//文件指针往前走 fputs("xxx", pf); fclose return 0; }
【函数部分说明】:
功能上:
返回值:
int main() { FILE* pf = fopen("test1.txt", "wb");//打开一个二级制文件 if (pf == NULL) { perror("fopen fail!!!"); return; } fputs("This is an apple", pf); fseek(pf, 0, SEEK_END); int size = ftell(pf); printf("%d", size);//size==16,源头到参考位置的字节数 fclose(pf); pf = NULL; return 0; }
【函数部分说明】:
int main() { FILE* pf = fopen("test1.txt", "wb");//打开一个二级制文件 if (pf == NULL) { perror("fopen fail!!!"); return; } fputs("This is an apple", pf); fseek(pf, 0, SEEK_END); rewind(pf); int size = ftell(pf); printf("%d", size); fclose(pf); pf = NULL; return 0; }
【牢记】:在文件读取过程中,不能用feof函数的返回值直接判断文件是否结束
【函数部分说明】:
【函数部分说明】:
功能:检查文件结束指示器
返回值:**如果设置了与流关联的文件结束指示符,则返回非零值。**否则,返回零。
文本文件读取是否结束:判断返回值是否为EOF(fgetc)或者NULL(fgets)
二进制文件读取是否结束:判断返回值是否小于实际要读的个数。
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");
ANSIC
标准采⽤“缓冲文件系统”处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的⼤⼩根据C编译系统决定的.上述过程转换为下图展示。
【验证】:
int main() { FILE*pf = fopen("test.txt", "w"); fputs("abcdef", pf);//先将代码放在输出缓冲区 printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n"); Sleep(10000); printf("刷新缓冲区\n"); fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘) //注:fflush 在⾼版本的VS上不能使⽤了 printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n"); Sleep(10000); fclose(pf); //注:fclose在关闭⽂件的时候,也会刷新缓冲区 pf = NULL; return 0; }
【目的】:
程序延迟执行时间内,检查文本编辑器是否存在数据,等待程序睡眠时间过去,再次检查文本编辑器是否存在数据,验证内存和外存之间存在缓冲区
【结论】:
因为有缓冲区的存在,C语⾔在操作文件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭文件。如果不做,可能导致读写⽂件的问题
以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二C语言笔记,希望对你在学习C语言中有所帮助!