You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将存储嵌套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();
}

关键注意事项

  1. POD类型检查:必须确保Frame、Struct A、Struct B都是可平凡复制类型。如果结构体包含非POD成员(比如std::string、std::vector),直接读写原始内存会导致数据损坏,此时需要手动序列化每个成员(比如逐个写入/读取float、bool等字段)。
  2. 跨平台兼容:不同编译器或操作系统的内存对齐规则可能不同,如果需要跨平台使用,建议放弃直接读写内存,改为手动序列化每个成员,避免因对齐差异导致的数据错误。
  3. 错误处理:代码中添加了文件打开失败的检查,实际使用时可以根据需求扩展错误处理逻辑(比如返回错误码、记录日志)。

内容的提问来源于stack exchange,提问作者Decode0007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 18:27:55