目录摘要一文件操作的流程1fopen2fclose3文件的路径4顺序和随机的区别5默认流二顺序读写函数1fputc2fgetc3fputs4fgets5fprintf6fscanf7fwite8fread摘要本博客介绍并使用8种顺序读写函数~一文件操作的流程读写的含义读读出即从文件里面读出数据-----------和scanf从键盘里面读出数据类似写写入即把数据写入文件里面-----------和printf把数据写入到屏幕上类似想对文件进行读写操作则流程一定为打开文件---读/写文件---关闭文件而我们对文件可能是只读可能是只写可能是追加可能是既读又写所以在使用fopen打开文件的时候函数规定需要在fopen的对应参数选择对应的打开模式~1fopenFILE * fopen ( const char * filename, const char * mode )参数解释参数类型说明filenameconst char *要打开的文件名可包含路径modeconst char *打开模式函数作用建立调用fopen的程序与filename文件之间的连接返回一个FILE *类型的指针供后续读写操作使用返回值成功返回FILE *失败返回NULL注意事项返回值为FILE*是结构体FILE的指针通过该指针可以进行文件的相关操作必须检查返回值后序读写前务必先判断fopen的返回值是否为NULL常用的打开模式如下文件使用方式含义如果指定文件不存在“r” (只读)为了输入数据打开一个已经存在的文本文件出错“w” (只写)为了输出数据打开一个文本文件建立一个新的文件“a” (追加)向文本文件尾添加数据建立一个新的文件“rb” (只读)为了输入数据打开一个二进制文件出错“wb” (只写)为了输出数据打开一个二进制文件建立一个新的文件“ab” (追加)向一个二进制文件尾添加数据建立一个新的文件“r” (读写)为了读和写打开一个文本文件出错“w” (读写)为了读和写建议一个新的文件建立一个新的文件“a” (读写)打开一个文件在文件尾进行读写建立一个新的文件“rb” (读写)为了读和写打开一个二进制文件出错“wb” (读写)为了读和写新建一个新的二进制文件建立一个新的文件“ab” (读写)打开一个二进制文件在文件尾进行读和写建立一个新的文件2fcloseint fclose ( FILE * stream );参数解释参数类型说明streamFILE *参数就是fopen的返回值函数作用关闭文件并且断开程序与文件之间的连接(顺便会刷新缓冲区)返回值返回值含义0关闭成功EOF通常是 -1关闭失败如缓冲区刷新失败、无效流指针等注意事项fclose关闭文件后安全起见必须将 FILE * 类型的fp设为 NULL但由于fclose一般都是代码的末尾执行后面也不会在使用fp所以往往会省去这一步但加上才是更优秀的做法所以文件操作的整体框架就为#include stdio.h int main() { //打开⽂件 FILE* pFile fopen(myfile.txt, w); //根据需求 进行⽂件读/写操作 //关闭文件 fclose(pFile); return 0; }3文件的路径在调用fopen时可以直接在第一个参数中传入文件名如data.txt此时系统会自动在当前工作目录下查找或创建该文件。当然也可以传入完整的绝对路径C:\\project\\data.txt来指定任意目录位置下的文件。某些打开模式是要求在指定路径下必须存在目标文件的所以当使用这些打开模式之前需要事先手动新建目标文件或者使用能够自动新建的写函数去创建文件而有些打开模式发现目录不存在会自动创建文件~4顺序和随机的区别顺序读写函数和随机读写函数都是因为存在文件位置指示器这个东西每次打开一个文件其对应的FILE结构体中就会维护着一个文件位置指示器也叫文件指针、文件偏移量它记录着下一次读写操作将从文件的哪个字节位置开始每次使用顺序读写函数后文件位置指示器会自动向后移动相应字节数因此读写操作会自然地形成顺序去进行读写而随机读写函数其可以修改文件位置指示器的值可以跳跃到文件的任意位置进行读写而不必按照顺序一个个处理所以叫做随机读写函数5默认流❓️那为什么scanf,printf的时候直接使用就行了不需要打开什么因为c语言程序只要运行起来就会默认打开3个流①标准输入流 stdin②标准输出流 stdout③标准错误流 stderr三个流的类型依然是 FILE*和读写函数的参数一致也可以理解为这一步电脑帮你省略了。都是与FILE * stream流有关流是什么流可以是文件从流里面读出数据写入数据到流里面只是不同的读写函数去读写的数据不一样一些是把单个字符写入到流或从流里读出单个字符一些是字符串的读写一些是二进制的读写二顺序读写函数顺序读写函数有8种如下函数名功能适用于fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets文本行输入函数所有输入流fputs文本行输出函数所有输出流fscanf格式化输入函数所有输入流fprintf格式化输出函数所有输出流fread二进制输入文件fwrite二进制输出文件解释上⾯说的适用于所有输入流⼀般指适用于标准输⼊流和其他输⼊流如文件输⼊流所有输出流⼀般指适用于标准输出流和其他输出流如文件输出流⚠️此篇博客都是对当前路径下的test.txt文件进行操作所以前后会有因果关系1fputcint fputc ( int character, FILE * stream );参数解释参数类型说明characterint要写入的字符的ascll码值streamFILE *指向要写入的文件流的指针注character也可以直接传递a这种字符因为字符的本质就是ascll码值(int类型)函数作用将字符写入到文件中成功写入后文件位置指示器自动向后移动一个字节返回值返回值含义int (写入的字符的ascll码值)写入成功EOF-1写入失败读取时到达文件尾或发生错误注意事项fputc作为写函数自然需要以写相关的打开模式去打开文件使用示例a写入单个字符#include stdio.h int main() { FILE* fp fopen(test.txt, w); if (fp NULL) { perror(打开文件失败); return 1; } fputc(A, fp); fclose(fp); return 0; }解释test.txt文件不存在所以fopen以写的形式打开文件的时候会先在指定路径下新建该文件这里的路径只有文件名字所以默认路径就是当前程序对应的目录文件如下b循环写入字符解释因为是w模式打开文件而不是追加模式所以下一次的写之前会清空上一次所写的内容2fgetcint fgetc ( FILE * stream );参数解释参数类型说明streamFILE *指向要读取的文件的FILE结构体函数作用从指定的文件流stream中读取一个字符返回值返回该字符的 ASCII 值。如果读取时到达文件尾或发生错误则返回EOFEnd Of File一个特殊的常量通常在大多数系统中定义为 -1注意事项会读取包括空格、换行在内的所有字符使用示例①读取单个字符#include stdio.h int main() { FILE* fp fopen(test.txt, r); if (fp NULL) { perror(打开文件失败); return 1; } int ch fgetc(fp); if (ch ! EOF) { printf(读取到的字符%c\n, ch); } fclose(fp); return 0; }②循环读取字符#include stdio.h int main() { FILE* fp fopen(test.txt, r); if (fp NULL) { perror(打开文件失败); return 1; } int ch; while ((ch fgetc(fp)) ! EOF) { putchar(ch); } fclose(fp); return 0; }解释fgetc无法读取时返回值为EOF所以当我们想循环读取文件的时候就可以使用返回值不为EOF进行判断从而循环地去读完整个文件3fputsint fputs ( const char * str, FILE * stream );参数解释参数类型说明strconst char *要写入的字符串以\0结尾streamFILE *指向要写入的文件流的指针函数作用将字符串写入到指定的文件流中将字符串str写入到文件流stream中且文件位置指示器会向后移动写入的字节数返回值返回值含义 0写入成功返回最后一个写入的非负字符数EOF-1写入失败注意事项fputs不会自动添加换行需要换行要手动加\n(否则两次fputs会出现在同一行)字符串必须以\0结尾否则fputs会一直找字符串中的\0可能会导致越界访问使用示例#include stdio.h int main() { FILE* fp fopen(test.txt, w); if (fp NULL) { perror(打开文件失败); return 1; } fputs(hello world, fp); fclose(fp); return 0; }解释写入了一个字符串因为是w方式打开文件所以之间的文件内容会被清空再写入4fgetschar * fgets ( char *str, int num, FILE * stream );参数解释参数类型说明strchar *字符串的指针该字符串用于存储读取到的字符串numint最多读取的字符个数包含结尾的\0streamFILE *指向要读取的文件流的指针函数作用从文件流stream中读取一个最大字符数为num-1的字符串str返回值返回值含义str传入的指针str读取成功NULL到达文件末尾或发生读取错误注意事项num参数包含了结尾的\0所以实际最多读num-1个字符缓冲区str要足够大至少num字节fgets停止读取的三种情况情况说明① 遇到换行符\n读取换行符将\n存入str然后停止末尾加\0② 已读取num-1个字符还没遇到换行符停止末尾加\0③ 遇到文件尾 EOF没有读到任何字符返回NULL如果读到部分字符后遇到 EOF也会停止并加\0❓️如果fgets读取的时候遇到了\0呢会提前停止吗不会fgets是把\0当作普通数据字符读取不会因为读到\0就停止验证示例我们往文件中写入字符A \0 B \n C然后再用fgets读取10个字节❓️为什么不用fputs直接写入字符串A\0B\nC因为fputs写入的时候遇到\0就会停止不再往后写入这是特性否则fputs停不下来#include stdio.h int main() { // 用 fputs 写入但 fputs 遇到 \0 会停止写入 FILE* fp fopen(test.txt, w); fputs(A, fp); fputc(\0, fp); // 手动写入 \0 fputs(B\nC, fp); fclose(fp); // 用 fgets 读取 fp fopen(test.txt, r); char buf[100] { 0 }; fgets(buf, 100, fp); for (int i 0; i 10; i) { printf(buf[%d] %d\n, i, buf[i]); } fclose(fp); return 0; }解释数组下标十进制值对应字符说明buf[0]65A从文件读取的第一个字符buf[1]0\0从文件读取的空字符fprintf写入的%cbuf[2]66B\0后面的B说明遇到\0没停止buf[3]10\n换行符遇到它fgets才停止读取buf[4]0\0fgets自动添加的字符串结束符buf[5~9]0\0缓冲区剩余空间被初始化为 0未使用部分这代表遇到第一个\0没有停止下来而遇到\n换行符才会停止❓️为什么要这么设置因为文本文件中压根就没有\0你在记事本中见过\0吗但是存在换行所以检测\n5fprintfint fprintf ( FILE * stream, const char * format, ... );参数解释参数类型说明streamFILE *指向要写入的文件流的指针formatconst char *格式控制字符串包含格式占位符如%d、%s等...可变参数对应格式占位符要输出的变量函数作用将格式化的数据写入到指定的文件流中返回值返回值含义 0成功写入的字符总数负数写入失败注意事项格式字符串与变量类型要匹配否则结果不可预料使用示例#include stdio.h int main() { FILE* fp fopen(test.txt, w); if (fp NULL) { perror(打开文件失败); return 1; } int age 25; float score 92.5; char name[] 张三; fprintf(fp, %s\n, name); fprintf(fp, %d\n, age); fprintf(fp, %.1f\n, score); //合成一行的写法 //fprintf(fp, %s %d %.1f\n, name, age, score); fclose(fp); fp NULL return 0; }解释说白了就是在printf的用法上增加一个FILE*类型的参数fp而已6fscanfint fscanf ( FILE * stream, const char * format, ... );参数解释参数类型说明streamFILE *指向要读取的文件流的指针formatconst char *格式控制字符串指定如何解析数据...可变参数对应格式占位符的变量地址用于存储读取的值函数作用从文件中读取格式化的数据返回值返回值含义正整数成功匹配并赋值的参数个数0没有匹配到任何数据但可能有字符被读取EOF-1读取时到达文件尾或发生错误注意事项功能与scanf完全相同区别是scanf从键盘读取fscanf从文件读取自动跳过空白字符空格、换行、制表符等遇到类型不匹配或文件尾时停止使用示例#include stdio.h int main() { FILE* fp fopen(test.txt, r); if (fp NULL) { perror(打开文件失败); return 1; } char name[50]; int age; float score; fscanf(fp, %s, name); fscanf(fp, %d, age); fscanf(fp, %f, score); printf(%s\n, name); printf(%d\n, age); printf(%.1f\n, score); fclose(fp); return 0; }解释说白了就是在scanf的用法上增加一个FILE*类型的参数fp而已7fwitesize_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );参数解释参数类型说明ptrconst void *指向要写入的数据的指针sizesize_t每个元素的大小字节数countsize_t要写入的元素个数streamFILE *指向要写入的文件流的指针函数作用将数据块以二进制的形式写入文件流fwrite从由ptr指向的内存块中取出count个元素每个元素的大小为size字节并将它们写入到stream指向的文件流中返回值返回值含义count成功写入的元素个数等于count表示全部成功 count部分写入成功通常表示磁盘满或发生错误注意事项文件通常以二进制模式打开wb、ab、wb写入的是原始二进制数据用记事本打开可能显示乱码返回的是元素个数不是字节数实际字节数 返回值 × size适合配合fread使用使用示例#include stdio.h int main() { FILE *fp fopen(test.txt, wb); if (fp NULL) { perror(打开文件失败); return 1; } int arr[] {10, 20, 30, 40, 50}; fwrite(arr, sizeof(int), 5, fp); fclose(fp); return 0; }解释fwrite以二进制的形式向test.txt文件中写入数据后我们此时打开test.txt文件就是乱码8freadsize_t fread ( void * ptr, size_t size, size_t count, FILE * stream );参数解释参数类型说明ptrvoid *指向存储读取数据的缓冲区的指针sizesize_t每个元素的大小字节数countsize_t要读取的元素个数streamFILE *指向要读取的文件流的指针函数作用从文件中以二进制形式读取数据到内存中适合读取数组、结构体等二进制数据文件位置指示器向后移动size × 实际读取的元素个数字节返回值返回值含义count成功读取的元素个数等于count表示全部成功 count部分读取成功可能到达文件尾或发生错误0没有读取到任何元素文件尾或错误注意事项文件通常以二进制模式打开rb、ab、rb读取的是原始二进制数据必须与写入时的格式完全一致缓冲区ptr必须足够大至少size × count字节适合配合fwrite使用使用示例#include stdio.h int main() { // 先写入数据 FILE* fp fopen(test.txt, wb); int arr1[] { 10, 20, 30, 40, 50 }; fwrite(arr1, sizeof(int), 5, fp); fclose(fp); // 再读取数据 fp fopen(test.txt, rb); int arr2[5]; fread(arr2, sizeof(int), 5, fp); for (int i 0; i 5; i) { printf(%d , arr2[i]); } fclose(fp); return 0; } [ 作者 ] shylyly [ 首次发布 ] 2024.3.28❌ [ 最新修改 ] 2026.10.14 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝赐教