如何将存储嵌套struct的std::vector写入文件并读取?
嵌套结构体的std::vector读写文件失败解决方案
问题背景
需要将包含大量嵌套结构体的std::vector<Frame>写入文件,之后再读取回vector。vector的结构如下:
std::vector<Frame> Frames - Frame(每个元素) - Struct A - float - float - bool ... - Struct B - float - float - bool ...
尝试了ofstream.write()、fwrite()以及std::copy配合流迭代器的方法均未成功,运行时报错:
binary '=': no operator found which takes a right-hand operand of type 'Frame' (or there is no acceptable conversion)
使用的错误代码如下:
void PosBot::SaveMacro(std::string macroName) { int val = _mkdir("PosBot"); std::string a = "PosBot/" + macroName + ".pbor"; std::ofstream outfile(a.c_str(), std::ios_base::binary); std::copy(Frames.begin(), Frames.end(), std::ostreambuf_iterator<char>(outfile)); outfile.close(); } void PosBot::LoadMacro(std::string macroName) { Frames.clear(); Checkpoints.clear(); CheckpointFrames.clear(); std::string a = "PosBot/" + macroName + ".pbor"; std::ifstream infile(a.c_str(), std::ios_base::binary); std::istreambuf_iterator<char> iter(infile); std::copy(iter, std::istreambuf_iterator<char>(), std::back_inserter(Frames)); // this leaves newVector empty infile.close(); }
错误原因
你用std::copy配合ostreambuf_iterator<char>、istreambuf_iterator<char>的方式完全错误:这些迭代器专门处理char类型的字节流,而你的vector元素是自定义的Frame结构体,直接这么做会导致类型不匹配,触发编译错误。此外,就算编译通过,这种方式也无法正确处理结构体的内存布局,读写后的数据会损坏。
正确实现方式
如果你的Frame及其内部的子结构体都是可平凡复制类型(即POD类型:无自定义构造/析构函数、无虚函数、成员都是POD类型),可以直接读写vector的原始内存,同时要先写入元素数量,方便读取时分配空间。
写入文件
void PosBot::SaveMacro(std::string macroName) { // 创建目录,忽略已存在的情况 _mkdir("PosBot"); std::string filePath = "PosBot/" + macroName + ".pbor"; std::ofstream outfile(filePath, std::ios::binary); if (!outfile.is_open()) { // 可在此添加错误处理,比如打印日志或抛出异常 return; } // 先写入元素总数,读取时需要用这个值确定vector大小 const size_t frameCount = Frames.size(); outfile.write(reinterpret_cast<const char*>(&frameCount), sizeof(frameCount)); // 写入所有Frame的原始数据 if (frameCount > 0) { outfile.write(reinterpret_cast<const char*>(Frames.data()), frameCount * sizeof(Frame)); } outfile.close(); }
读取文件
void PosBot::LoadMacro(std::string macroName) { Frames.clear(); Checkpoints.clear(); CheckpointFrames.clear(); std::string filePath = "PosBot/" + macroName + ".pbor"; std::ifstream infile(filePath, std::ios::binary); if (!infile.is_open()) { // 错误处理 return; } // 先读取元素总数 size_t frameCount = 0; infile.read(reinterpret_cast<char*>(&frameCount), sizeof(frameCount)); // 分配空间并读取数据 Frames.resize(frameCount); if (frameCount > 0) { infile.read(reinterpret_cast<char*>(Frames.data()), frameCount * sizeof(Frame)); } infile.close(); }
关键注意事项
- POD类型检查:必须确保
Frame、Struct A、Struct B都是可平凡复制类型。如果结构体包含非POD成员(比如std::string、std::vector),直接读写原始内存会导致数据损坏,此时需要手动序列化每个成员(比如逐个写入/读取float、bool等字段)。 - 跨平台兼容:不同编译器或操作系统的内存对齐规则可能不同,如果需要跨平台使用,建议放弃直接读写内存,改为手动序列化每个成员,避免因对齐差异导致的数据错误。
- 错误处理:代码中添加了文件打开失败的检查,实际使用时可以根据需求扩展错误处理逻辑(比如返回错误码、记录日志)。
内容的提问来源于stack exchange,提问作者Decode0007
相关产品推荐
相关产品推荐

