首先我们需要知道几个问题1.为什么使⽤⽂件2.什么是⽂件3.⼆进制⽂件和⽂本⽂件4.⽂件的打开和关闭5.⽂件的顺序读写6.⽂件的随机读写7.⽂件读取结束的判定8.⽂件缓冲区一 为什么使用文件如果没有⽂件我们写的程序的数据是存储在电脑的内存中如果程序退出内存回收数据就丢失 了等再次运⾏程序是看不到上次程序的数据的如果要将数据进⾏持久化的保存我们可以使⽤ ⽂件。二什么是文件1.磁盘硬盘上的⽂件是⽂件。 但是在程序设计中我们⼀般谈的⽂件有两种程序⽂件、数据⽂件从⽂件功能的⻆度来分类 的。2.程序⽂件 程序⽂件包括源程序⽂件后缀为.c,⽬标⽂件windows环境后缀为.obj,可执⾏程序windows 环境后缀为.exe。3数据⽂件 ⽂件的内容不⼀定是程序⽽是程序运⾏时读写的数据⽐如程序运⾏需要从中读取数据的⽂件或 者输出内容的⽂件。 本章讨论的是数据⽂件。 在以前各章所处理数据的输⼊输出都是以终端为对象的即从终端的键盘输⼊数据运⾏结果显⽰到 显⽰器上。 其实有时候我们会把信息输出到磁盘上当需要的时候再从磁盘上把数据读取到内存中使⽤这⾥处 理的就是磁盘上⽂件。4 ⽂件名 ⼀个⽂件要有⼀个唯⼀的⽂件标识以便⽤⼾识别和引⽤。 ⽂件名包含3部分⽂件路径⽂件名主⼲⽂件后缀 例如 c:\code\test.txt 为了⽅便起⻅⽂件标识常被称为⽂件名。三⼆进制⽂件和⽂本⽂件根据数据的组织形式数据⽂件被分为⽂本⽂件和⼆进制⽂件。 数据在内存中以⼆进制的形式存储如果不加转换的输出到外存的⽂件中就是⼆进制⽂件。 如果要求在外存上以ASCII码的形式存储则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂ 本⽂件。 ⼀个数据在⽂件中是怎么存储的呢 字符⼀律以ASCII形式存储数值型数据既可以⽤ASCII形式存储也可以使⽤⼆进制形式存储。 如有整数10000如果以ASCII码的形式输出到磁盘则磁盘中占⽤5个字节每个字符⼀个字节⽽ ⼆进制形式输出则在磁盘上只占4个字节。四⽂件的打开和关闭-----流的概念我们程序的数据需要输出到各种外部设备也需要从外部设备获取数据不同的外部设备的输⼊输出 操作各不相同为了⽅便程序员对各种设备进⾏⽅便的操作我们抽象出了流的概念我们可以把流 想象成流淌着字符的河。 C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。 ⼀般情况下我们要想向流⾥写数据或者从流中读取数据都是要打开流然后操作。-----标准流在c语言中会默认打开一些流来供我们使用stdin-标准输⼊流stdout-标准输出流stderr-标准错误流当然他们的类型都是FILE*类型的流我们在后续的使用也会用到这个类型来创作一些流首先介绍两个函数1-》fopen---用来打开文件的函数FILE * fopen ( const char * filename, const char * mode );filename-要打开文件的名字以什么路径进行打开的mode-以什么方式来打开的比如读写追加。返回值成功FILE*类型的指针失败返回空所以我们打开的时候要进行判空。2-》fclose---用来关闭文件的函数注意这关闭文件不会直接将FILE*类型的指针置为空我们要手动的置为空来进行后续的操作我们在文件中一般分为三部分1.打开文件 2.操作文件 3.关闭文件这三部分来展开进行int main() { //操作打开文件 FILE * psfopen(D:\\课件\\./../test1.txt,a);// /-调整上一级 if (ps ! NULL) { printf(文件打开成功\n); } else { perror(文件打开失败原因是); //文件打开失败原因是: No such file or directory } //操作文件 //关闭文件 fclose(ps);//将ps给关闭用法和free一样 ps NULL; if (ps NULL) { printf(文件已关闭\n); } return 0; }别忘了关闭文件的时候要手动置为空防止后续使用出现错误当然代开文件有读写追加那么我们要用什么来进行呢我们有这么多的方法进行添加要注意的是用’w‘进行写源文件的信息会丢失的所以源文件的信息要是有用的话就不要进行w可以选择追加或者”rb“进行操作我们有了这些方法该如何去做呢接下来我们就要进行系统的说明了五⽂件的顺序读写这里我们还要使用一些函数来进行这些操作fputsint fputc ( int character, FILE * stream );1.stream---你打开文件所用的流2.character---你要输入的字符返回值成功时返回写⼊的字符失败时返回 EOF 通常是-1错误指⽰器会被设置可通过ferror来进行判断演示 写入A-Zint main() { 开启文件 FILE* a fopen(文件使用.txt, w); if (a EOF) { perror(a fail); exit(1); } printf(文件打开成功\n); //写文件 for (int i A; i Z; i) { fputc(i, a); } //关闭文件 fclose(a); a NULL; if (a NULL) { printf(文件关闭成功\n); } return 0; }fgetcint fgetc ( FILE * stream );功能从参数 stream 指向的流中读取⼀个字符。函数返回的是⽂件指⽰器当前指向的字符读取这 个字符之后⽂件指⽰器⾃动前进道下⼀个字符。 参数 stream :FILE*类型的⽂件指针可以是 stdin 也可以是其他输⼊流的指针。如果是 stdin 就 从标准输⼊流读取数据。如果是⽂件流指针就从⽂件读取数据。返回值 • 成功时返回读取的字符以 int 形式。• 若调⽤时流已处于⽂件末尾函数返回 若发⽣读取错误函数返回 EOF 并设置流的⽂件结束指⽰器 EOF 并设置流的错误指⽰器 ferror 。打印刚才写入的A-Z的所有数for (int i 1; i 26; i) { char cfgetc(a); printf(%c, c); } printf(\n);feofint feof ( FILE * stream );检测 stream 指针指向的流是否遇到⽂件末尾说人话就是你的文件的光标指向的位置ferrorint ferror ( FILE * stream );fputs and getsint fputs ( const char * str, FILE * stream );str--要写入的字符串stream--文件流返回值成功---非负整数失败---EOFchar * fgets ( char * str, int num, FILE * stream );str--读取到的字符数组num--读取的字符个数stream--流返回首字符的地址/指针这里提到的后续会讲到文件从一开始计数int main() { //打开文件 FILE* pr fopen(文件使用.txt, w); if (pr NULL) { perror(fopen fail!); exit(1); } char arr[20] { 0 }; //文件操作 fputs(hello word, pr); fflush(pr);//强制刷新缓冲区让写的数据先到后 rewind(pr);//让光标回到起始位置 fgets(arr, 6, pr); printf(%s\n, arr); //关闭文件 fclose(pr); pr NULL; }输出结果fprintf它可以指定类型输出前面介绍的只能输入字符串而这个可以传任何类型int fprintf ( FILE * stream, const char * format, ... );功能 fprintf 是将格式化数据写⼊指定⽂件流的函数。它与 printf 类似但可以输出到任意 ⽂件如磁盘⽂件、标准输出、标准错误等⽽不仅限于控制台。stream--流其他的和printf相同返回值• 成功时返回写⼊的字符总数⾮负值。• 失败时先设置对应流的错误指⽰器再返回负值可以通过 ferror() 来检测。对应的代码和文件内部的情况struct ass { char name[20]; char sex[10]; int age; char dizhi[20]; }s1; int main() { //打开文件 FILE* pr fopen(文件使用.txt, w); if (pr NULL) { perror(fopen fail!); exit(1); } scanf(%s %s %d %s, s1.name,s1.sex,s1.age,s1.dizhi); fprintf( pr,姓名%s性别%s年龄%d,地址: %s, s1.name, s1.sex, s1.age, s1.dizhi); //关闭文件 fclose(pr); pr NULL; }fscanfint fscanf ( FILE * stream, const char * format, ... );stream--流其他的和scanf一样他是读取一个数据覆盖到另一个• 成功时函数返回成功填充到参数列表中的项数。该值可能与预期项数⼀致也可能因以下原因少 于预期甚⾄为零fwritesize_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );用来写2进制的可以是不同类型ptr--要写入的数据size-数据的大小(以字节为单位count--要写入的个数stream--流freadsize_t fread ( void * ptr, size_t size, size_t count, FILE * stream );使用二进制可以重要的信息保存的更好这样可以对数据的更好的保护别人打开二进制是乱码的样子我们使用的时候想要看的时候将文件添加进去然后改成添加现有项打开方式改成二进制的形式就能看到里面的数据了.sprintfint sprintf ( char * str, const char * format, ... );功能将格式化数据写⼊字符数组字符串。它类似于 printf 但输出⽬标不是控制台或⽂件 ⽽是⽤⼾指定的内存缓冲区。常⽤于动态⽣成字符串、拼接数据或转换数据格式。简⽽⾔之就是将格 式化的数据转换成⼀个字符串。参数• str 指向字符数组的指针⽤于存储⽣成的字符串需确保⾜够⼤以防⽌溢出。• fo rmat 格式化字符串定义输出格式如 %d 、 %f 、 %s 等。 • ... 可变参数列表提供与格式字符串中说明符对应的数据。返回值• 成功时返回写⼊ buffer 的字符数不包括结尾的空字符 \0 。• 失败时返回负值这里实现一下结果采用调试的结果来看一下sscanfint sscanf ( const char * str, const char * format, ...);功能从字符串中读取格式化数据。它与 scanf 类似但输⼊源是内存中的字符串⽽⾮控制台或⽂ 件。常⽤于解析字符串中的结构化数据如提取数字、分割⽂本等。参数• str 要解析的源字符串输⼊数据来源。• format 格式化字符串定义如何解析数据如 %d 、 %f 、 %s 等。• ... 可变参数列表提供存储数据的变量地址需与格式字符串中的说明符匹配返回值• 成功时返回成功解析并赋值的参数数量⾮负值。• 失败或未匹配任何数据若输⼊结束或解析失败返回EOF这里采用调试的方法:这里将我们所见到的printf and fprintf and sprintfscanf and fscanf and sscanf六. ⽂件的随机读写fseekint fseek ( FILE * stream, long int offset, int origin );stream--流originorigin--这个很重要是要结合返回值的offset---要结合前一个数让光标是正序,中序,后序的回几个SEEK_SET是回到是首位置光标前进几个位置SEEK_CUR是当前位置前进几个位置SEEK_END回到末尾来前进几个位置这里origin一般选负数这里都是在0的开始进行的比如给1--0走一步---1走一步是两部int main() { FILE* pr fopen(文件使用.txt,w); if (pr NULL) { perror(文件打开失败); exit(1); } for (int i A; i Z; i) { fputc(i, pr);//将A-Z的数写入文件 } //这样我们读文件的时候光标在最后一个 fflush(pr);//刷新一下将数据强制将缓冲区强制到文件 fseek(pr,3,SEEK_SET);//回到初始位置读取的我应该是D printf(%c\n, fgetc(pr)); fseek(pr, 1, SEEK_CUR);//从当前位置向后走一个应该是F printf(%c\n, fgetc(pr)); fseek(pr, -1, SEEK_END);//结尾走应该是Y printf(%c\n, fgetc(pr)); //关闭文件 fclose(pr); pr NULL; return 0; }ftelllong int ftell ( FILE * stream );计算当前位置距离初始位置返回值是距离rewind是将光标直接回到起始距离void rewind ( FILE * stream );七. ⽂件缓冲区ANSI C标准采⽤“缓冲⽂件系统”处理数据⽂件的所谓缓冲⽂件系统是指系统⾃动地在内存中为程 序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲 区装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据则从磁盘⽂件中读取数据输⼊ 到内存缓冲区充满缓冲区然后再从缓冲区逐个地将数据送到程序数据区程序变量等。缓冲 区的⼤⼩根据C编译系统决定的。fflushint fflush ( FILE * stream );功能强制刷新参数 stream 指定流的缓冲区确保数据写⼊底层设备。• 对输出流将缓冲区中未写⼊的数据⽴即写⼊⽂件。• 对输⼊流⾏为由具体实现决定⾮C语⾔标准⾏为可能清空输⼊缓冲区• 参数为 NULL 时刷新所有打开的输出流参数 stream 指向⽂件流的指针如 stdout 、⽂件指针等返回值成功返回 0 失败返回 EOF注意事项 1. 仅对输出流或更新流最后⼀次操作为输出有明确刷新⾏为 2. 输⼊流的刷新⾏为不可移植如清空输⼊缓冲区是⾮标准特性 3. 程序正常终⽌ exit 或调⽤ fclose 时会⾃动刷新但程序崩溃时缓冲区数据可能丢失