以二进制模式读写文件必须显式指定std::ios::binary标志,否则Windows下会自动转换换行符;read()/write()按字节操作,需确保内存布局匹配、缓冲区已分配并检查gcount()或流状态。

用 std::ifstream 和 std::ofstream 以二进制模式打开文件
关键不是函数本身,而是打开时必须显式指定 std::ios::binary 标志,否则 Windows 下会把 \x0A 和 \x0D\x0A 自动转换,导致读写不一致。
常见错误:只写 std::ofstream("data.bin") —— 这是文本模式,write() 写入的 \x0A 可能在 Windows 上变成两个字节。
std::ofstream file("data.bin", std::ios::binary);std::ifstream file("data.bin", std::ios::binary);- 若需同时读写,加
std::ios::in | std::ios::out
read() 和 write() 的参数必须严格匹配内存布局
这两个成员函数不进行类型解析,只按字节搬运。传入的指针必须指向连续、已分配的内存,且第二个参数是字节数(不是元素个数)。
容易踩的坑:write(&vec, sizeof(vec)) 错误——std::vector 对象本身只存指针、size、capacity,不包含实际数据;正确做法是 write(vec.data(), vec.size() * sizeof(int))(假设是 vector)。
立即学习“C++免费学习笔记(深入)”;
- 写结构体前确保它不含虚函数、引用、非 POD 成员,否则
sizeof(T)不等于实际可序列化大小 - 读取时缓冲区必须提前分配好空间,
read()不会自动扩容 - 调用后务必检查
gcount()(返回实际读取字节数)或!file状态
struct Record {
int id;
double value;
};
Record r = {42, 3.14159};
std::ofstream out("record.bin", std::ios::binary);
out.write(reinterpret_cast(&r), sizeof(r)); 跨平台二进制读写要注意字节序和对齐
直接读写原生类型(如 int、double)在不同 CPU 架构间不可移植:x86 是小端,PowerPC 可能是大端;结构体对齐也因编译器和平台而异。
如果文件需要被其他程序或机器读取,不要依赖 write() 原样 dump 内存。
- 网络传输或长期存储建议手动序列化:用
htons()/htonl()统一为大端,再write() - 结构体加
#pragma pack(1)或[[gnu::packed]]避免填充字节,但要确认目标平台支持 - 浮点数尤其危险:
double的 IEEE 754 表示虽通用,但某些嵌入式平台可能不兼容
用 readsome() 或循环 read() 处理不确定长度数据
read() 是阻塞式且不保证一次读完请求的全部字节(尤其对管道、网络流),但对普通文件通常能一次完成。不过仍需检查返回值。
更安全的做法是循环读取直到满足预期字节数或遇到 EOF:
std::ifstream in("data.bin", std::ios::binary);
std::vector buf(1024);
in.read(buf.data(), buf.size());
std::streamsize n = in.gcount();
if (n != static_cast(buf.size()) && !in.eof()) {
// 出错了,比如磁盘满、权限不足
} 注意:readsome() 只读当前缓冲区中已有的字节,不触发底层 read 系统调用,一般不用在文件场景。
二进制读写最易忽略的是状态检查和平台差异——哪怕代码在本地跑通了,换台机器或改个编译选项就可能静默出错。










