c++中如何进行二进制读写_c++ read与write二进制文件方法【详解】

14次阅读

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

c++中如何进行二进制读写_c++ read与write二进制文件方法【详解】

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

关键不是函数本身,而是打开时必须显式指定 std::ios::binary 标志,否则 windows 下会把 x0Ax0Dx0A 自动转换,导致读写不一致。

常见错误:只写 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));

跨平台二进制读写要注意字节序和对齐

直接读写原生类型(如 intdouble)在不同 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 系统调用,一般不用在文件场景。

二进制读写最易忽略的是状态检查和平台差异——哪怕代码在本地跑通了,换台机器或改个编译选项就可能静默出错。

text=ZqhQzanResources