必须显式使用std::ios::binary标志打开二进制文件,否则windows会自动转换换行符;write()原样写入内存字节,需注意类型大小、字节序、结构体填充及跨平台兼容性,并及时flush和检查状态。

用 std::ofstream 以二进制模式打开文件
不加 std::ios::binary 标志,Windows 下换行符会被悄悄替换成 \r\n,Linux 虽不改但行为不一致——这会导致写入的原始字节和预期不符,尤其在跨平台传输或读取时直接出错。
- 必须显式传入
std::ios::binary,比如:std::ofstream file("data.bin", std::ios::out | std::ios::binary); - 如果还要追加写入,得再加
std::ios::app;想清空重写,就别带std::ios::app,默认会覆盖 - 打开后务必检查
file.is_open(),否则后续write()不报错但什么都不发生
用 write() 写原始内存块
write() 不做任何编码转换、不加结束符、不解释内容——它只管把内存里连续的一段字节原样塞进文件。所以你得自己确保传进去的是“真·二进制数据”,而不是字符串字面量或未初始化的缓冲区。
- 参数是
const char*和std::streamsize,不能直接传int或std::string:要写一个int x = 42;,得用file.write(reinterpret_cast<const char>(&x), sizeof(x));</const> - 写
std::string的内容(不含结尾\0):用str.data()+str.size(),别用str.c_str(),后者可能多一个隐式\0 - 结构体可直接写,但要注意内存对齐和填充字节——
struct里有std::string或指针就绝对不能这么干
注意字节序和类型大小的硬约束
写进去的 int 在 x86_64 是小端、4 字节,但读它的程序可能跑在大端 ARM 上,或者用 long 当 8 字节读——结果就是数值完全错乱,而且很难 debug。
- 跨平台或存档场景下,别依赖
sizeof(int),固定用int32_t/uint64_t等明确宽度的类型 - 网络协议或长期存储,建议手动拆成字节写(如
static_cast<uint8_t>(val >> 24)</uint8_t>),或用htons()/htonl()统一转为大端 - 浮点数更危险:
float写进去,另一端用double读,不仅精度炸,还可能因 ABI 差异读偏位
关闭前别忘了 flush() 和检查写入状态
文件流析构时会自动 flush 并 close,但万一中间断电或程序崩溃,缓冲区里还没落盘的数据就丢了——而 write() 成功返回只代表进了缓冲区,不代表已写入磁盘。
- 关键数据写完立刻调
file.flush(),尤其是日志或配置保存场景 - 检查
file.good()或!file.fail(),别只看write()返回值;写失败时failbit可能被设上,但流对象本身还“活着” - 磁盘满、权限不足等错误不会抛异常(默认不开启
exceptions()),只能靠状态位判断
write(&obj, sizeof(obj)),半年后换了个编译器或平台,读出来全是垃圾。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











