最常用高效方式是用std::ofstream二进制模式直接写数组内存块;必须显式指定std::ios::binary标志,用write()配合reinterpret_cast,注意数组长度、类型固定宽度、pod结构体要求、字节序处理及文件版本管理。

用 std::ofstream 以 binary 模式写入数组
直接把数组内存块写进文件是最常用、最高效的方式。关键不是“怎么存”,而是“别用文本模式”——默认的 ofstream 会做换行符转换(比如 \n → \r\n),二进制数据就全乱了。
实操要点:
- 必须显式指定
std::ios::binary标志,例如:std::ofstream file("data.bin", std::ios::binary) - 用
write()写原始字节:file.write(reinterpret_cast<const char>(arr), sizeof(arr))</const>(注意reinterpret_cast是必需的,write只接受const char*) - 数组若为局部变量(如
int arr[100]),sizeof(arr)可用;若为指针(如int* arr = new int[100]),必须自己记下长度,用len * sizeof(int)
保存前要写入数组长度吗?
绝大多数情况下要。否则读取时根本不知道该读多少字节——尤其是数组长度不固定、或文件后续还要追加其他数据时。
常见做法是“头+体”结构:
- 先写一个整数(如
uint32_t)表示元素个数,再写数据本体 - 类型必须固定宽度(推荐
std::uint32_t而非int),避免不同平台sizeof(int)不一致 - 如果数组元素是自定义结构体,确保它不含指针、虚函数、或非 POD 成员,否则
reinterpret_cast写出的是无效内存镜像
示例片段:
uint32_t len = 100; file.write(reinterpret_cast<const char>(&len), sizeof(len)); file.write(reinterpret_cast<const char>(arr), len * sizeof(*arr));</const></const>
跨平台读写要注意字节序
如果你写的文件要在不同 CPU 架构(比如 x86 和 ARM)或不同操作系统上读,小端/大端不一致会导致数值错乱。C++ 标准库不自动处理这个。
解决方式很简单:
- 约定统一用小端(x86/AMD64 默认)或大端(网络字节序),并在读写时手动转换
- 写入前用
htole32()(host to little-endian)或htonl()(host to network = big-endian);读取后用对应反向函数 - Windows 需要
#include <winsock2.h></winsock2.h>并链接ws2_32.lib;Linux/macOS 直接可用endian.h或byteswap.h
用 fwrite 还是 std::ofstream::write?
两者都能用,但行为有细微差别:
-
fwrite是 C 风格,更底层,错误只能靠返回值判断(返回实际写入项数),没异常机制 -
std::ofstream::write支持异常模式(file.exceptions(std::ios::failbit | std::ios::badbit)),出错时抛异常,更容易捕获磁盘满、路径无权限等真实问题 - 性能几乎无差别,现代标准库实现通常对
write做了优化;优先选std::ofstream,和 C++ RAII 管理更自然
别忘了检查写入是否成功——即使开了异常,也要确认 file.good() 或在作用域结束前调用 file.close() 并检查 file.fail(),因为缓冲区可能在析构时才真正刷盘。
最容易被忽略的是:二进制文件没有“格式版本”概念。一旦你改了数组类型或结构体布局,旧文件就无法安全读取。真要长期保存,得在文件头里加入 magic number 和 version 字段,并在读取时校验。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











