C语言 1000问 · 文件I/O Q1:fopen 的文本模式和二进制模式(b)有什么区别?换行符在两种模式下怎么处理?
来源:Flomo 原始笔记|查看原笔记|迁移日期:2026-10-31
C语言 1000问 · 文件I/O Q1:fopen 的文本模式和二进制模式(b)有什么区别?换行符在两种模式下怎么处理?
▎ 五大学习法:西蒙学习法——把「文本 vs 二进制」钻透
fopen 的模式
- “r” / “w” / “a”:文本模式读 / 写 / 追加。
- “rb” / “wb” / “ab”:二进制模式。
- 加 ”+“:可读可写(如 “r+”、“rb+”)。
本质区别:换行符的翻译(主要在 Windows)
- 文本模式:库会翻译换行。Windows 上写文件时把 ‘\n’ 自动转成 “\r\n”,读文件时把 “\r\n” 转回 ‘\n’——C 程序里始终只处理 ‘\n’,跨平台代码不用管差异。
- 二进制模式:不做任何翻译,字节原样进出。读到的 0x0D 0x0A 就是 0x0D 0x0A,不会合并成 ‘\n’。
两个关键差异
- 换行翻译:只在 Windows / DOS 这类以 CRLF 为行尾的系统上明显;Linux / macOS(Unix)里两种模式基本无差别(都按 ‘\n’ 处理)。
- 特殊字节处理:某些老系统(CP/M、老 DOS)文本模式遇到 0x1A(Ctrl-Z)当 EOF,二进制模式不会。现代系统基本没这问题,但跨平台代码要注意。
为什么二进制文件必须用 “b”
- 图片、音频、可执行文件、协议报文、结构体直接 dump——里面字节可能恰是 0x1A、0x0D 0x0A。
- 若用文本模式打开,这些字节可能被翻译或误判 EOF,文件内容就被破坏。
- 所以:只要文件不是「人类可读的文本行」,一律用 “rb” / “wb”。
实践建议
- 读写对象是二进制数据 → 永远带 b,保证跨平台字节一致。
- 只处理文本、且只在 Unix 上跑 → 带不带 b 无所谓。
- 要跨平台处理文本 → 用文本模式让库翻译换行,或自己统一成 ‘\n’(很多协议、嵌入式日志就这么做)。
- 嵌入式文件系统(FATFS 等)常按二进制处理,换行约定自己定。
一个常见坑
- 文本模式下 fseek / ftell 的位置在 Windows 上可能因翻译而不等于真实字节偏移——要按字节定位就用二进制模式。
- fopen 失败返回 NULL,一定要检查;写出错要查 ferror 和 fclose 的返回值。
一句话:文本模式会按平台翻译换行(Windows 上 ‘\n’ 与 “\r\n” 互转),二进制模式字节原样进出;凡是二进制数据一律加 b,文本看平台——这就是带不带 b 的全部意义。
📎 问题库(专栏⑭导航)→ https://v.flomoapp.com/mine/?memo_id=MjQ1NzM0NTk5
📎 预处理器Q3(高级用法)→ https://v.flomoapp.com/mine/?memo_id=MjU2MzEyNzY4