C++二进制文件读写string与char[]选型及操作相关技术咨询
C++ 二进制.dat文件读写常见问题解答
1、读写.dat格式二进制文件时,选用string还是char[]更合适?
没有绝对最优的选择,完全看业务场景:
- 如果是固定长度字段的结构体整体序列化场景(比如高校管理系统里限定姓名最多16字符、学院名最多32字符),选char[]更合适,开发成本更低
- 如果是动态长度的二进制内容存储、不需要按固定大小偏移随机读写的场景,可以用string
2、通常情况下C++读写二进制文件的最优实现方式是什么?
分两类场景对应最优实现:
- 固定长度结构体批量读写:
- 首先给结构体添加
#pragma pack(1)编译器指令,取消内存对齐带来的填充字节 - 打开文件时必须指定
std::ios::binary标志,避免Windows下自动转义换行符损坏二进制内容 - 直接调用fstream的
read/write方法整体读写结构体,和参考案例的file.read/write((char *)this, sizeof(类名))用法一致,性能最高,开发成本最低
- 首先给结构体添加
- 动态长度内容读写:
- 采用「长度头 + 实际内容」的存储格式
- 写入时先写内容长度,再写对应长度的二进制数据;读取时先读长度,再读对应字节数的内容,避免越界
3、多数C++项目中普遍使用char[]而非string做二进制写入,背后原因是什么?
核心原因是和整体序列化结构体的开发模式不兼容:std::string是动态容器,它的内部成员只有指向堆内存的指针、长度、容量三个值,直接把包含string的结构体整体写入文件时,写进去的只是指针地址,不是实际的字符串内容,读取时这个指针地址早就失效了,访问直接崩溃。
而char[]是结构体内部的固定长度数组,内存直接包含在结构体的地址空间里,整体序列化时可以直接把完整内容写入文件,读出来就能直接用,完全适配参考案例里的简洁写法,不需要额外写序列化逻辑,开发效率高。
另外还有两个次要原因:
- 固定长度char[]的存储不需要额外处理长度字段,文件格式更简单,随机读写时直接按结构体大小偏移即可,不需要解析动态长度
- 很多老项目有兼容C语言的需求,char[]是C/C++通用类型,跨语言交互也更方便
4、如何使用string完成二进制文件的读写操作?
注意不能直接对包含string的结构体做整体序列化,要单独处理每个string字段,采用「先写长度、再写内容」的逻辑,示例代码如下:
#include <fstream> #include <string> int main() { // 写入string到二进制文件 std::ofstream out_file("student.dat", std::ios::binary); std::string college = "计算机科学与技术学院"; // 先写入字符串长度 size_t str_len = college.size(); out_file.write(reinterpret_cast<const char*>(&str_len), sizeof(str_len)); // 再写入字符串实际内容 out_file.write(college.data(), str_len); out_file.close(); // 从二进制文件读取string std::ifstream in_file("student.dat", std::ios::binary); size_t read_len = 0; // 先读取长度 in_file.read(reinterpret_cast<char*>(&read_len), sizeof(read_len)); std::string read_college; // 提前分配对应长度的空间 read_college.resize(read_len); // 读取实际内容到string中 in_file.read(read_college.data(), read_len); in_file.close(); return 0; }
注意:如果需要跨平台读写,要额外处理大小端问题,避免不同平台对长度值的字节序解析错误。
内容的提问来源于stack exchange,提问作者Loay Tarek
相关产品推荐
相关产品推荐

