C 语言通过标准库中的 fopen() 函数来打开文件,这个函数的第二个参数就是文件模式字符串,根据这个模式,C 语言主要可以处理以下两大类文件:

(图片来源网络,侵删)
文本文件
这是最常见、最基础的文件类型,文本文件中的数据以人类可读的字符形式存储,每个字符通常用一个 ASCII 或 Unicode 编码(如 UTF-8)来表示。
核心特点:
- 可读性: 可以用任何文本编辑器(如记事本、VS Code、Sublime Text)打开并直接阅读。
- 存储方式: 数据被转换成字符的序列,整数
123在内存中是二进制形式,但在写入文本文件时,会被转换成字符'1','2','3'的 ASCII 码(十进制 49, 50, 51)。 - 平台差异: 文本中的换行符在不同操作系统上可能不同(Windows 是
\r\n,Linux/macOS 是\n),但 C 标准库会进行一定的处理,使得你的程序在跨平台时行为一致。
C 语言处理方式:
使用 "r", "w", "a", "r+", "w+", "a+" 等模式进行读写,操作时,主要使用 fprintf(), fscanf(), fgets(), fputs() 等函数,它们会自动在内存中的二进制形式和文本字符之间进行转换。
常见文件扩展名:

(图片来源网络,侵删)
.txt(纯文本文件).c,.h(C 源代码文件).csv(逗号分隔值文件).xml,.json,.html(标记语言文件).ini,.conf,.log(配置和日志文件).md(Markdown 文件)
示例:
#include <stdio.h>
int main() {
// 以写入模式打开一个文本文件
FILE *fp = fopen("example.txt", "w");
if (fp == NULL) {
perror("无法打开文件");
return 1;
}
// fprintf 会将整数 123 和字符串 "Hello" 转换成文本写入文件
fprintf(fp, "The number is %d and a string: %s\n", 123, "Hello");
fclose(fp);
// 以读取模式打开
fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("无法打开文件");
return 1;
}
int number;
char str[50];
// fscanf 会从文本文件中扫描并转换成对应的整数和字符串
fscanf(fp, "The number is %d and a string: %s\n", &number, str);
printf("从文件读取到: number = %d, string = %s\n", number, str);
fclose(fp);
return 0;
}
执行后,example.txt 文件的内容就是:The number is 123 and a string: Hello
二进制文件
二进制文件中的数据是内存中数据的直接、未经转换的副本,它不关心数据是否代表可读字符,只是按字节原样写入和读取。
核心特点:

(图片来源网络,侵删)
- 不可读性: 用文本编辑器打开会看到一堆乱码。
- 存储方式: 数据直接以二进制形式存储,整数
123在内存中通常占用 4 个字节(0x7B),写入二进制文件时,就是直接写入这 4 个字节。 - 高效: 没有文本转换的开销,读写速度更快,文件体积通常更小(尤其是对于数字等数据)。
- 精确性: 能完整地保存数据在内存中的状态,包括所有位信息,不会因格式转换而丢失精度。
C 语言处理方式:
使用 "rb", "wb", "ab", "rb+", "wb+", "ab+" 等模式(注意 b 代表 binary),操作时,主要使用 fwrite() 和 fread() 函数,它们直接在内存地址和文件之间进行数据块的拷贝。
常见文件扩展名:
.dat(通用数据文件).bin(二进制可执行文件或数据).obj,.o(目标文件).jpg,.png,.gif(图像文件).mp3,.wav,.avi(音视频文件).exe,.dll(Windows 可执行文件和动态链接库)- 数据库文件(如
.db,.sqlite)
示例:
#include <stdio.h>
// 定义一个结构体来演示
typedef struct {
int id;
float score;
char name[20];
} Student;
int main() {
Student s1 = {101, 95.5f, "Alice"};
Student s2;
// 以二进制写入模式打开文件
FILE *fp = fopen("student.dat", "wb");
if (fp == NULL) {
perror("无法打开文件");
return 1;
}
// fwrite 会将整个结构体 s1 的内容直接以二进制形式写入文件
size_t items_written = fwrite(&s1, sizeof(Student), 1, fp);
if (items_written != 1) {
perror("写入文件失败");
fclose(fp);
return 1;
}
fclose(fp);
// 以二进制读取模式打开文件
fp = fopen("student.dat", "rb");
if (fp == NULL) {
perror("无法打开文件");
return 1;
}
// fread 会从文件中读取 sizeof(Student) 大小的数据到 s2 的内存地址
size_t items_read = fread(&s2, sizeof(Student), 1, fp);
if (items_read != 1) {
perror("读取文件失败");
fclose(fp);
return 1;
}
fclose(fp);
// 打印读取到的结构体内容
printf("从文件读取到: id = %d, score = %.2f, name = %s\n", s2.id, s2.score, s2.name);
return 0;
}
这个例子中,student.dat 文件的内容是不可读的二进制数据,但它精确地保存了 s1 对象的所有信息。
总结与对比
| 特性 | 文本文件 | 二进制文件 |
|---|---|---|
| 可读的字符序列 | 内存数据的直接副本 | |
| 读写函数 | fprintf, fscanf, fgets, fputs |
fwrite, fread |
| 可读性 | 高,可用文本编辑器打开 | 低,显示为乱码 |
| 存储效率 | 较低,有转换开销 | 较高,无转换开销,体积小 |
| 数据精度 | 可能丢失精度(如浮点数) | 精确保存,无精度损失 |
| 适用场景 | 配置文件、日志、源代码、数据交换 | 图像、音频、视频、可执行文件、需要高效读写大量数据的场景 |
C 语言能处理所有文件类型吗?
理论上,是的,但前提是:
- 文件是字节流: C 语言将所有文件都视为一个连续的字节序列,只要一个文件能被表示为字节流,C 语言就有能力打开和读写它。
- 理解文件格式: C 语言提供了读写原始字节的能力,但它不理解特定文件内部的格式,C 语言可以打开一个
.jpg文件并读取它的所有字节,但它不知道哪些字节是文件头,哪些是像素数据,要正确处理.jpg文件,你需要自己编写一个 JPEG 解码器,或者使用第三方库(如 libjpeg)。
C 语言是文件的“搬运工”,而不是“翻译官”。 它能帮你把文件内容从硬盘搬到内存,或者从内存写回硬盘,但如何解读这些内容,需要程序员根据具体的文件格式来实现。
