三维数组二进制保存必须用write(),不能用operator

三维数组二进制保存必须用 write(),不能用 operator
因为 operator 是格式化输出,会把数字转成字符串(比如 123 写成三个字节 '1','2','3'),而你想要的是原始内存布局。只有 std::ofstream::write() 能直接把内存块原样写入文件。
常见错误现象:read() 读出来全是 0 或乱码,或者大小不对——基本就是用了流插入操作符或没指定 std::ios::binary 模式。
- 打开文件时务必加
std::ios::binary标志,否则 Windows 下换行符会被悄悄转换 - 确保数组是连续内存(如
int arr[2][3][4]或std::vector),非连续(如 vector of vector of vector)不能直接flat(2*3*4) write() - 写入前用
sizeof(arr)或total_size * sizeof(T)算准字节数,别漏乘sizeof(int)这种
嵌套循环写入只适合「非连续内存」,且效率低
如果你的三维结构是 std::vector<:vector>>> 这种指针套指针的形式,内存不连续,那就没法一整块 write(),只能靠三层 for 循环逐个元素写。
但注意:每次 write() 一个 double(8 字节)会触发系统调用开销,比批量写慢几倍到几十倍;而且容易因忘记 sizeof(double) 导致写错字节数。
- 每轮循环内必须写
out.write(reinterpret_cast,(&val), sizeof(val)) &val不可省略取地址 - 如果中间某层
vector长度不一致(比如arr[i].size()不固定),必须在循环里动态算偏移,不能硬编码维度 - 更稳妥的做法是先展平(flatten)到一维
std::vector,再整块写——哪怕多一次拷贝,也比嵌套循环 + 小写入快且安全
std::ofstream::write() 的参数顺序和类型必须严格匹配
函数原型是 write(const char*, streamsize),第一个参数必须是 const char*,第二个是字节数(不是元素个数)。C++ 不做隐式转换,write(arr, sizeof(arr)) 对栈数组可行,但对 std::vector 必须用 .data() 和 .size() * sizeof(T)。
典型错误:write(arr, 2*3*4) —— 这只写了 24 字节,但 int 是 4 字节,实际该写 96 字节;又或者传 arr[0][0] 地址却按整个三维算大小,导致越界或截断。
- 栈上定义的
float data[10][20][30]:用out.write(reinterpret_cast(data), sizeof(data)) -
std::vector:用flat(10*20*30) out.write(reinterpret_cast(flat.data()), flat.size() * sizeof(float)) - 千万别对
std::vector直接用sizeof(vec)——那只是 vector 对象本身大小(通常 24 字节),不是数据大小
读取时维度信息必须单独保存,二进制文件不带元数据
纯二进制文件只存数值,不存“这是 10×20×30 的 float 数组”这种信息。下次读的时候,如果维度错了,数据就全错位——比如按 5×40×30 读 10×20×30 的数据,每个 float 值都会被错当成相邻位置的值。
建议做法:在二进制数据前写 3 个 int(或 uint32_t),明确记录 dim_x、dim_y、dim_z,读取时先读这 12 字节,再按尺寸分配内存并读后续数据。
- 写入顺序示例:
out.write(reinterpret_cast→ 同样写 dy、dz → 最后写数据块(&dx), sizeof(dx)); - 使用固定宽度整型(如
uint32_t)避免不同平台int大小不一致的问题 - 如果要跨平台或长期存档,考虑加魔数(magic number)和版本号,比如开头写 4 字节
0x44415433("DAT3" ASCII)
二进制保存本身很简单,难的是维度对齐、内存连续性判断、以及读写两端对“怎么解释这一串字节”的约定是否完全一致——漏掉任何一个,文件就能成功生成,但内容永远读不对。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











