1. C语言文件读写概述
做嵌入式开发这些年,我越来越觉得文件操作是个被低估的技能。很多人觉得「单片机又没文件系统,学这个干嘛?」——但你想想看,等你做Linux嵌入式、做数据采集、做日志系统的时候,文件操作就是基本功了。今天咱们就从头捋一遍,把文件读写的底裤扒干净。
1.1 为什么需要文件操作?
说白了,程序跑在内存里,内存一断电就没了。文件操作解决的就是「数据持久化」的问题。我遇到过不少新手,调试时把数据打印到串口,关掉电源就啥也找不到了。嗯,这时候你就知道文件的重要性了。
具体来说,文件操作能帮你做这些事:
- 数据持久化:程序退出后,数据还能留在磁盘上
- 批量处理:从文件读入大量数据,而不是手动一个个敲
- 配置管理:程序启动时读取配置文件,灵活调整参数
- 日志记录:记录运行状态、错误信息,方便排查问题
- 跨进程通信:不同程序通过文件交换数据
核心观点:文件操作是C语言连接「内存世界」和「磁盘世界」的桥梁。不会文件操作,你的程序就是个「过目就忘」的傻子。
1.2 文件类型:文本文件 vs 二进制文件
这个问题我当年也迷糊过。其实区分很简单——就看文件里存的是「人能看懂的字」还是「机器能读懂的字节」。
| 对比项 | 文本文件 | 二进制文件 |
|---|---|---|
| 存储内容 | 字符序列(ASCII/UTF-8编码) | 字节序列(原样存储) |
| 可读性 | 用记事本打开能看懂 | 打开是乱码 |
| 典型扩展名 | .txt, .c, .h, .csv | .bin, .dat, .exe, .jpg |
| 换行处理 | Windows下\r\n,Linux下\n | 不做任何转换 |
| 适用场景 | 配置文件、日志、源代码 | 图片、音频、可执行程序、结构体数据 |
我的经验:在嵌入式开发中,如果你要保存结构体数据(比如传感器采集的浮点数数组),用二进制文件更高效。文本文件虽然可读,但读写速度慢,还占空间。我曾经在一个项目中用文本文件存100万个采样点,结果文件大了3倍,解析还慢得要命——后来改成二进制,问题秒解。
1.3 文件操作的基本流程
文件操作其实就三步走:打开 → 读写 → 关闭。听起来简单,但每一步都有坑。我画了个流程图,帮你理清思路:
你看,流程很清晰。但这里我要强调一个关键点——每次打开文件后,一定要检查返回值。我见过太多人直接拿fopen的返回值就用,结果文件没打开,程序直接崩了。
⚠️ 避坑指南:我曾经在一个数据采集项目中,忘记检查fopen的返回值。结果SD卡没插好,文件打开失败,程序却继续往下写数据——所有采集的数据全丢了,白忙活一整天。从那以后,我每条fopen后面必跟NULL判断,成了肌肉记忆。
1.4 一个完整的例子
光说不练假把式。咱们写个最简单的例子,把「Hello World」写到文件里,再读出来:
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp;
char buffer[100];
// 1. 打开文件(写模式)
fp = fopen("test.txt", "w");
if (fp == NULL) {
printf("文件打开失败!\n");
return -1;
}
// 2. 写入数据
fprintf(fp, "Hello, 文件操作!\n");
fprintf(fp, "这是第二行。\n");
// 3. 关闭文件
fclose(fp);
// 4. 重新打开(读模式)
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf("文件打开失败!\n");
return -1;
}
// 5. 读取并打印
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("读到:%s", buffer);
}
// 6. 关闭文件
fclose(fp);
return 0;
}
💡 小技巧:注意我用了两次fclose。很多人只关一次,但如果你要切换读写模式,最好先关掉再打开。虽然某些系统允许你直接切换,但为了可移植性,我建议你养成「用完就关」的习惯。
1.5 文件操作模式速查
fopen的第二个参数是个字符串,决定了你怎么操作文件。我整理了个速查表:
| 模式 | 含义 | 文件不存在时 | 文件存在时 |
|---|---|---|---|
"r" |
只读 | 返回NULL | 正常打开 |
"w" |
只写 | 创建新文件 | 清空内容 |
"a" |
追加 | 创建新文件 | 在末尾写入 |
"r+" |
读写 | 返回NULL | 正常打开 |
"w+" |
读写 | 创建新文件 | 清空内容 |
"a+" |
读写追加 | 创建新文件 | 在末尾读写 |
记住:带 b 的模式(如 "rb"、"wb")用于二进制文件。在Linux下文本和二进制没区别,但在Windows下差别很大——文本模式会自动转换换行符,二进制模式不会。我建议你统一用二进制模式,省得跨平台时出幺蛾子。
好了,这一章咱们把文件操作的基本概念和流程捋清楚了。下一章开始,我会带你深入每个函数的细节,包括那些文档里不会写的坑。嗯,准备好你的编译器,咱们要动手了。
可可精品资料库