多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# C 文件处理 > 原文: [https://www.programiz.com/c-programming/c-file-input-output](https://www.programiz.com/c-programming/c-file-input-output) #### 在本教程中,您将学习 C 语言中的文件处理。您将学习在示例的帮助下使用`fprintf()`,`fscanf()`,`fread()`,`fwrite()`,`fseek()`等在 C 中处理标准 I/O。 文件是计算机存储设备中用于存储数据的容器。 * * * ## 为什么需要文件? * 当程序终止时,所有数据都会丢失。 即使程序终止,存储在文件中也会保留您的数据。 * 如果必须输入大量数据,则将花费大量时间来全部输入。 但是,如果您有一个包含所有数据的文件,则可以使用 C 中的一些命令轻松访问该文件的内容。 * 您可以轻松地将数据从一台计算机移动到另一台计算机,而无需进行任何更改。 * * * ## 文件类型 处理文件时,您应该了解两种类型的文件: 1. 文本文件 2. 二进制文件 ### 1.文本文件 文本文件是普通的`.txt`文件。 您可以使用任何简单的文本编辑器(例如记事本)轻松创建文本文件。 打开这些文件时,您将以纯文本形式看到文件中的所有内容。 您可以轻松地编辑或删除内容。 它们以最少的维护工作,易于读取,提供最少的安全性并占用更大的存储空间。 ### 2.二进制文件 二进制文件主要是计算机中的`.bin`文件。 它们不是以纯文本格式存储数据,而是以二进制格式(0 和 1)存储数据。 与文本文件相比,它们可以容纳更多数据,不易读取,并提供更好的安全性。 * * * ## 文件操作 在 C 中,您可以对文件执行四个主要操作,即文本或二进制: 1. 创建一个新文件 2. 打开现有文件 3. 关闭文件 4. 读取信息并将信息写入文件 * * * ## 处理文件 处理文件时,需要声明文件类型的指针。 文件和程序之间的通信需要此声明。 ```c FILE *fptr; ``` * * * ## 打开文件 - 用于创建和编辑 使用`stdio.h`头文件中定义的`fopen()`函数执行打开文件。 在标准 I/O 中打开文件的语法为: ```c ptr = fopen("fileopen","mode"); ``` 例如, ```c fopen("E:\\cprogram\\newprogram.txt","w"); fopen("E:\\cprogram\\oldprogram.bin","rb"); ``` * 假设文件`newprogram.txt`在位置`E:\cprogram`中不存在。 第一个函数创建一个名为`newprogram.txt`的新文件,并根据`'w'`模式打开该文件进行写入。 写入模式允许您创建和编辑(覆盖)文件的内容。 * 现在,我们假设第二个二进制文件`oldprogram.bin`存在于位置`E:\cprogram`中。 第二个函数打开现有文件,以二进制模式`'rb'`读取。 读取模式仅允许您读取文件,而不能写入文件。 标准 I/O 中的打开模式 | 模式 | 模式的含义 | 文件不存在期间 | | --- | --- | --- | | `r` | 打开以读取。 | 如果文件不存在,则`fopen()`返回`NULL`。 | | `rb` | 打开以二进制模式读取。 | 如果文件不存在,则`fopen()`返回`NULL`。 | | `w` | 打开以写入。 | 如果文件存在,其内容将被覆盖。如果文件不存在,将创建它。 | | `wb` | 打开以二进制方式写入。 | 如果文件存在,其内容将被覆盖。如果文件不存在,将创建它。 | | `a` | 打开进行附加。数据添加到文件末尾。 | 如果文件不存在,将创建它。 | | `ab` | 打开以二进制方式附加。数据添加到文件末尾。 | 如果文件不存在,将创建它。 | | `r+` | 打开以读取和写入。 | 如果文件不存在,则`fopen()`返回`NULL`。 | | `rb+` | 打开以二进制方式读取和写入。 | 如果文件不存在,则`fopen()`返回`NULL`。 | | `w+` | 打开以读取和写入。 | 如果文件存在,其内容将被覆盖。如果文件不存在,将创建它。 | | `wb+` | 打开以二进制方式读取和写入。 | 如果文件存在,其内容将被覆盖。如果文件不存在,将创建它。 | | `a+` | 打开以读取和附加。 | 如果文件不存在,将创建它。 | | `ab+` | 打开以读取和附加二进制模式。 | 如果文件不存在,将创建它。 | * * * ## 关闭文件 读取/写入后,应关闭文件(文本文件和二进制文件)。 使用`fclose()`函数关闭文件。 ```c fclose(fptr); ``` 在此,`fptr`是与要关闭的文件相关联的文件指针。 * * * ## 读取和写入文本文件 为了读取和写入文本文件,我们使用函数`fprintf()`和`fscanf().` 它们只是`printf()`和`scanf()`的文件版本。 唯一的区别是`fprint()`和`fscanf()`需要指向结构`FILE`的指针。 * * * ### 示例 1:写入文本文件 ```c #include <stdio.h> #include <stdlib.h> int main() { int num; FILE *fptr; // use appropriate location if you are using MacOS or Linux fptr = fopen("C:\\program.txt","w"); if(fptr == NULL) { printf("Error!"); exit(1); } printf("Enter num: "); scanf("%d",&num); fprintf(fptr,"%d",num); fclose(fptr); return 0; } ``` 该程序从用户那里获取一个号码,并将其存储在文件`program.txt`中。 编译并运行该程序后,您会看到在计算机的 C 驱动器中创建的文本文件`program.txt`。 打开文件时,您可以看到输入的整数。 * * * ### 示例 2:读取文本文件 ```c #include <stdio.h> #include <stdlib.h> int main() { int num; FILE *fptr; if ((fptr = fopen("C:\\program.txt","r")) == NULL){ printf("Error! opening file"); // Program exits if the file pointer returns NULL. exit(1); } fscanf(fptr,"%d", &num); printf("Value of n=%d", num); fclose(fptr); return 0; } ``` 该程序读取`program.txt`文件中存在的整数并将其打印到屏幕上。 如果您从**示例 1** 成功创建了文件,运行此程序将为您提供输入的整数。 其他函数,例如`fgetchar()`,`fputc()`等也可以类似的方式使用。 * * * ## 读写二进制文件 对于二进制文件,函数`fread()`和`fwrite()`分别用于读取和写入磁盘上的文件。 * * * ### 写入二进制文件 要写入二进制文件,需要使用`fwrite()`函数。 这些函数采用四个参数: 1. 要写入磁盘的数据地址 2. 要写入磁盘的数据大小 3. 此类数据的数量 4. 指向要写入的文件的指针。 ```c fwrite(addressData, sizeData, numbersData, pointerToFile); ``` * * * ### 示例 3:使用`fwrite()`写入二进制文件 ```c #include <stdio.h> #include <stdlib.h> struct threeNum { int n1, n2, n3; }; int main() { int n; struct threeNum num; FILE *fptr; if ((fptr = fopen("C:\\program.bin","wb")) == NULL){ printf("Error! opening file"); // Program exits if the file pointer returns NULL. exit(1); } for(n = 1; n < 5; ++n) { num.n1 = n; num.n2 = 5*n; num.n3 = 5*n + 1; fwrite(&num, sizeof(struct threeNum), 1, fptr); } fclose(fptr); return 0; } ``` 在此程序中,我们在 C 驱动器中创建一个新文件`program.bin`。 我们用三个数字 - `n1`,`n2`和`n3`声明结构`threeNum`,并在主函数中将其定义为`num`。 现在,在`for`循环中,我们使用`fwrite()`将值存储到文件中。 第一个参数采用`num`的地址,第二个参数采用结构`threeNum`的大小。 由于我们仅插入一个`num`的实例,因此第三个参数是`1`。 并且,最后一个参数`*fptr`指向我们正在存储数据的文件。 最后,我们关闭文件。 * * * ### 从二进制文件读取 函数`fread()`也采用 4 个自变量,类似于上面的`fwrite()`函数。 ```c fread(addressData, sizeData, numbersData, pointerToFile); ``` * * * ### 示例 4:使用`fread()`从二进制文件读取 ```c #include <stdio.h> #include <stdlib.h> struct threeNum { int n1, n2, n3; }; int main() { int n; struct threeNum num; FILE *fptr; if ((fptr = fopen("C:\\program.bin","rb")) == NULL){ printf("Error! opening file"); // Program exits if the file pointer returns NULL. exit(1); } for(n = 1; n < 5; ++n) { fread(&num, sizeof(struct threeNum), 1, fptr); printf("n1: %d\tn2: %d\tn3: %d", num.n1, num.n2, num.n3); } fclose(fptr); return 0; } ``` 在此程序中,您将读取同一文件`program.bin`,并逐个循环浏览记录。 简单来说,就是从`* fptr`指向的文件中读取`threeNum`大小的`threeNum`记录到结构`num`中。 您将获得与在**示例 3** 中插入的记录相同的记录。 * * * ## 使用`fseek()`获取数据 如果文件中有很多记录,并且需要访问特定位置的记录,则需要遍历所有记录才能获取该记录。 这将浪费大量的内存和操作时间。 使用`fseek()`可以更轻松地获取所需数据。 顾名思义,`fseek()`将光标定位到文件中的给定记录。 * * * ### `fseek()`的语法 ```c fseek(FILE * stream, long int offset, int whence); ``` 第一个参数流是指向文件的指针。 第二个参数是要查找的记录的位置,第三个参数指定偏移量开始的位置。 `fseek()`中的不同`whence` | `whence` | 含义 | | --- | --- | | `SEEK_SET` | 从文件开头开始偏移。 | | `SEEK_END` | 从文件末尾开始偏移。 | | `SEEK_CUR` | 从文件中光标的当前位置开始偏移。 | * * * ### 示例 5:`fseek()` ```c #include <stdio.h> #include <stdlib.h> struct threeNum { int n1, n2, n3; }; int main() { int n; struct threeNum num; FILE *fptr; if ((fptr = fopen("C:\\program.bin","rb")) == NULL){ printf("Error! opening file"); // Program exits if the file pointer returns NULL. exit(1); } // Moves the cursor to the end of the file fseek(fptr, -sizeof(struct threeNum), SEEK_END); for(n = 1; n < 5; ++n) { fread(&num, sizeof(struct threeNum), 1, fptr); printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3); fseek(fptr, -2*sizeof(struct threeNum), SEEK_CUR); } fclose(fptr); return 0; } ``` 该程序将以相反的顺序(从最后到第一)开始从文件`program.bin`中读取记录并进行打印。