c++如何进行二进制文件读写_c++ binary file操作【实战】

4次阅读

必须显式指定std::ios::binary标志,否则windows下会因0x1A被误判为EOF而截断数据;read()/write()需传原始内存地址和字节数,结构体需处理填充和字节序。

c++如何进行二进制文件读写_c++ binary file操作【实战】

std::fstreamstd::ios::binary 模式打开文件

默认的 std::fstream 是文本模式,会自动转换换行符(比如 rnn),破坏二进制数据。必须显式指定 std::ios::binary 标志:

std::fstream file("data.bin", std::ios::in | std::ios::out | std::ios::binary); if (!file.is_open()) {     // 处理失败 }
  • 读写同开时,std::ios::in | std::ios::out 是必要组合;只读用 std::ios::in,只写用 std::ios::out
  • windows 下若漏掉 std::ios::binary,读到的字节数可能少于预期,尤其遇到 0x1A(EOF 符)会被提前截断
  • linux/macOS 对文本/二进制模式区分不敏感,但跨平台代码必须统一加 std::ios::binary

read()write() 的参数与常见错误

这两个函数操作的是原始内存块,不是字符串对象本身,参数必须严格匹配:

int value = 42; file.write(reinterpret_cast(&value), sizeof(value)); // 正确:取地址 + 强转 + 显式大小  char buf[1024]; file.read(buf, sizeof(buf)); // 正确:传入缓冲区首地址和字节数
  • read() 不会自动在末尾加 ,读完后若要当 C 字符串用,需手动置零或确保缓冲区初始化
  • 读取后务必检查 file.gcount() —— 它返回实际读到的字节数,可能小于请求值(如文件结尾、磁盘满)
  • 直接 file.write(&str, sizeof(str))std::String 对象是错的:它只写对象内部指针/长度字段,不是字符串内容

结构体写入前要注意内存对齐和字节序

直接 write() 结构体可行,但有隐含风险:

struct Header {     uint32_t magic;   // 通常 4 字节     uint16_t version; // 通常 2 字节     char name[32]; };
  • 编译器可能在字段间插入填充字节(padding),导致 sizeof(Header) > 实际数据长度;用 #pragma pack(1)[[gnu::packed]] 强制紧凑布局
  • 不同 CPU 架构字节序不同(x86 是小端,ARM 可能大端),网络传输或跨平台读写时,需手动用 htons()/htonl() 转换整数字段
  • 含指针或虚函数的类不能直接二进制序列化 —— 指针值在另一进程毫无意义

写完记得 flush() 和检查 failbit

二进制写入出错不会抛异常(默认不开启 exceptions()),全靠状态位判断:

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

file.write(data, size); if (file.fail()) {     // 可能是磁盘满、权限不足、设备断开等     // 注意:fail() 包含 badbit(底层 I/O 错误)和 failbit(格式/逻辑错误) } file.flush(); // 确保缓冲区数据真正落盘,尤其在程序可能崩溃前
  • 不调 flush() 就关闭文件,部分数据可能滞留在缓冲区中丢失
  • file.good() 是“全无错误”的快捷判断,但定位问题不如分别查 fail()bad()eof()
  • 频繁小块写入性能差,建议预分配缓冲区 + 批量 write(),或用 std::vector 管理内存

实际项目里最常被忽略的是结构体填充和字节序 —— 看似写进去了,换台机器或换个编译器就打不开。

text=ZqhQzanResources