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

使用nlohmann json存储含二维数组的结构体 替代易崩溃的boost序列化方案

实现方案

1. 基于nlohmann json的序列化方法

首先需要确保自定义类型Items已经实现了对应的json序列化/反序列化逻辑,再对MyStruct做如下适配:

#include <nlohmann/json.hpp>
#include <fstream>
#include <string>

using json = nlohmann::json;

// 先实现Items的json转换,以下为示例,根据Items的实际结构调整
struct Items {
    int id;
    std::string content;
};
void to_json(json& j, const Items& item) {
    j = json{{"id", item.id}, {"content", item.content}};
}
void from_json(const json& j, Items& item) {
    j.at("id").get_to(item.id);
    j.at("content").get_to(item.content);
}

// MyStruct的json转换实现
void to_json(json& j, const MyStruct& s) {
    // 二维数组转json嵌套数组
    json item_arr = json::array();
    for (int i = 0; i < 100; ++i) {
        json row = json::array();
        for (int col = 0; col < 60; ++col) {
            row.push_back(s.item[i][col]);
        }
        item_arr.push_back(row);
    }
    j = json{
        {"item", item_arr},
        {"Something", s.Something},
        {"X", s.X},
        {"Y", s.Y}
    };
}
void from_json(const json& j, MyStruct& s) {
    j.at("Something").get_to(s.Something);
    j.at("X").get_to(s.X);
    j.at("Y").get_to(s.Y);
    // 解析二维数组
    auto& item_arr = j.at("item");
    for (int i = 0; i < 100; ++i) {
        auto& row = item_arr.at(i);
        for (int col = 0; col < 60; ++col) {
            row.at(col).get_to(s.item[i][col]);
        }
    }
}

// 保存接口
void SaveJson(const std::string& name, const MyStruct& test) {
    std::ofstream out(name + ".json");
    json j = test;
    out << j.dump(4); // 不需要格式化可直接调用dump()
}

// 读取接口
MyStruct ReadJson(const std::string& filename) {
    std::ifstream in(filename + ".json");
    json j;
    in >> j;
    return j.get<MyStruct>();
}

json方案优势是可读性强、跨版本跨平台兼容性好,缺点是大体积数组序列化时性能和存储空间占用不如二进制方案。


2. 无Boost依赖的二进制序列化方案

你之前用Boost偶尔崩溃的核心原因大概率是没有指定二进制模式打开文件,Windows下文本模式会自动转换换行符,破坏二进制数据结构;另外Boost二进制存档本身存在跨版本不兼容的问题。

手动实现的二进制序列化方案如下,无任何第三方依赖,稳定性更高:

#include <fstream>
#include <string>

// 如果Items是非POD类型,参考std::string处理逻辑单独实现序列化/反序列化方法即可
void SaveBinary(const std::string& name, const MyStruct& test) {
    std::ofstream out(name + ".dat", std::ios::binary);
    // 序列化基础类型字段
    out.write(reinterpret_cast<const char*>(&test.X), sizeof(test.X));
    out.write(reinterpret_cast<const char*>(&test.Y), sizeof(test.Y));
    // 序列化字符串:先存长度再存内容
    size_t str_len = test.Something.size();
    out.write(reinterpret_cast<const char*>(&str_len), sizeof(str_len));
    out.write(test.Something.data(), str_len);
    // 序列化固定大小二维数组,Items为POD类型可直接批量写入
    out.write(reinterpret_cast<const char*>(&test.item), sizeof(test.item));
    out.close();
}

MyStruct ReadBinary(const std::string& filename) {
    MyStruct test{};
    std::ifstream in(filename + ".dat", std::ios::binary);
    // 读取基础字段
    in.read(reinterpret_cast<char*>(&test.X), sizeof(test.X));
    in.read(reinterpret_cast<char*>(&test.Y), sizeof(test.Y));
    // 读取字符串
    size_t str_len = 0;
    in.read(reinterpret_cast<char*>(&str_len), sizeof(str_len));
    test.Something.resize(str_len);
    in.read(test.Something.data(), str_len);
    // 读取二维数组
    in.read(reinterpret_cast<char*>(&test.item), sizeof(test.item));
    in.close();
    return test;
}

如果需要跨平台使用,仅需额外处理大小端转换、固定字段字节长度即可,兼容性完全可控。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:15:04