C++怎么读写二进制文件_C++高效IO教程【紧凑】

二进制文件读写必须显式指定std::ios::binary标志,使用read()/write()而非格式化io,并检查gcount()/good();跨平台需处理字节序、内存对齐;关闭前需flush()并检查fail()。

C++怎么读写二进制文件_C++高效IO教程【紧凑】

std::ifstreamstd::ofstream 以二进制模式打开文件

默认的文本模式会做换行符转换(比如 nrn),读写结构体或原始字节时直接崩。必须显式指定 std::ios::binary 标志。

常见错误:只写 std::ios::instd::ios::out,漏掉 binary,结果数据错位、读到一半就 eof() 了。

  • std::ifstream fin("data.bin", std::ios::in | std::ios::binary);
  • std::ofstream fout("data.bin", std::ios::out | std::ios::binary);
  • 追加写入用 std::ios::app | std::ios::binary,但注意 app 模式下 seekp() 无效

读写原始内存块:别用 operator 和 <code>operator>>

这两个是格式化 IO,会解析空格、换行、类型分隔符,对二进制数据完全不可控。必须用 read()write() 直接操作字节流。

典型翻车现场:把一个 struct Point { int x, y; } 写进去,再用 <code>>> 读,结果 y 总是 0 —— 因为中间被当作文本分隔符吃了。

立即学习C++免费学习笔记(深入)”;

  • 写结构体:fout.write(reinterpret_cast<const char>(&p), sizeof(p));</const>
  • 读结构体:fin.read(reinterpret_cast<char>(&p), sizeof(p));</char>
  • 务必检查 gcount()good()read() 可能只读部分字节(比如磁盘满、中断)

跨平台写结构体前,先处理字节序和内存对齐

直接 write() 结构体看似快,但 struct 在不同编译器/平台下可能有填充字节(padding),且整数默认是本地字节序(小端/大端不统一)。发给 Python 或网络另一端时大概率解不开。

不是所有场景都要手撸序列化,但只要涉及跨语言、跨机器、长期存储,就不能跳过这步。

  • #pragma pack(1)alignas(1) 消除 padding(注意性能代价)
  • 关键字段(如 int32_t)用 htons()/htonl()std::byteswap() 统一为大端
  • 更稳的做法:逐字段 write() + 显式类型长度(比如固定写 4 字节 int32_t,而非 sizeof(int)

关闭文件前记得 flush() 和检查 fail()

析构函数会自动 close,但写失败不会抛异常,也不会提示你数据根本没落盘。尤其在嵌入式或低资源环境,缓存未刷导致静默丢数据很常见。

很多人以为 ofstream 离开作用域就万事大吉,其实 write() 成功只代表进了缓冲区,close() 才真正触发系统调用。

  • 显式调用 fout.flush() 后检查 !fout.fail()
  • 关闭后检查 !fout.fail(),失败时查 errno(Linux)或 GetLastError()(Windows)
  • 如果要确保原子写入,得用临时文件 + rename(),C++ 标准库不提供该语义

二进制 IO 的坑不在语法,而在“看起来写进去了”和“真的能被正确还原”之间那几行没写的检查与适配。