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

C++如何读写包含std::string、std::vector的变长结构体到二进制文件

问题根本原因

你遇到的问题本质是std::string、std::vector这类动态容器的内存布局不是连续存储实际内容:结构体里只保存了指向堆内存的指针、长度等元数据,直接fwrite结构体只会把指针地址、固定大小的元数据写入文件,实际的字符串内容、vector存储的数值都不会被写入,读取回来的指针指向的是无效内存,自然无法正常使用。

可行实现方案

方案1:手动实现序列化(无第三方依赖,可控性最高)

你可以按照固定的自定义格式逐字段写入/读取,不需要依赖任何外部库,适合轻量场景:

写入逻辑(单条entry为例)

// 写入单个entry到文件
void write_entry(FILE* fp, const entry& e) {
    // 1. 写入固定大小的id
    fwrite(&e.id, sizeof(uint64_t), 1, fp);
    // 2. 写入name的长度,再写入name的实际内容
    size_t name_len = e.name.size();
    fwrite(&name_len, sizeof(size_t), 1, fp);
    fwrite(e.name.data(), sizeof(char), name_len, fp);
    // 3. 写入data的长度,再写入data的所有元素
    size_t data_len = e.data.size();
    fwrite(&data_len, sizeof(size_t), 1, fp);
    fwrite(e.data.data(), sizeof(uint64_t), data_len, fp);
}

// 写入整个vector
void write_entry_vector(FILE* fp, const std::vector<entry>& vec) {
    // 可选:先写入总条目数,读取的时候可以先读总大小提前分配vector空间
    size_t total = vec.size();
    fwrite(&total, sizeof(size_t), 1, fp);
    for (const auto& e : vec) {
        write_entry(fp, e);
    }
}

读取逻辑(单条entry为例)

// 从文件读取单个entry
void read_entry(FILE* fp, entry& e) {
    // 1. 读取id
    fread(&e.id, sizeof(uint64_t), 1, fp);
    // 2. 读取name长度,再读取内容赋值给string
    size_t name_len = 0;
    fread(&name_len, sizeof(size_t), 1, fp);
    e.name.resize(name_len);
    fread(e.name.data(), sizeof(char), name_len, fp);
    // 3. 读取data长度,再读取所有元素赋值给vector
    size_t data_len = 0;
    fread(&data_len, sizeof(size_t), 1, fp);
    e.data.resize(data_len);
    fread(e.data.data(), sizeof(uint64_t), data_len, fp);
}

// 读取整个vector
void read_entry_vector(FILE* fp, std::vector<entry>& vec) {
    size_t total = 0;
    fread(&total, sizeof(size_t), 1, fp);
    vec.resize(total);
    for (size_t i = 0; i < total; i++) {
        read_entry(fp, vec[i]);
    }
}

注意事项

  • 如果你的文件需要跨平台使用,要统一处理字节序:写入时把数值转成大端(网络字节序),读取时转成本地字节序,避免不同CPU架构的字节序差异导致数据错乱。
  • 如果后续结构体可能迭代修改,建议在文件最开头写入版本号,不同版本对应不同的读写逻辑,保证向前兼容。

方案2:使用成熟的序列化库(适合复杂场景)

如果你的数据结构后续会频繁迭代,或者需要支持跨语言读写,可以直接用现成的序列化框架,不需要自己处理字节序、字段兼容问题:

  • Protobuf:通用型强,压缩率和性能均衡,需要先写.proto结构定义文件生成序列化代码
  • FlatBuffers:适合性能要求极高的场景,不需要 unpack 就可以直接读取数据
  • nlohmann/json:可以序列化为BSON等二进制格式,不需要额外写定义,使用简单但性能相对低一些

核心原则

序列化的核心逻辑是:所有动态长度的字段,都要先写长度再写实际内容,读写顺序严格保持一致,只要遵守这个原则,不管是手动实现还是用第三方库,都不会出现数据错乱的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:57:04