大数跨境

C++ 好用的序列化开源库 -- Cereal

C++ 好用的序列化开源库 -- Cereal 国科慧安
2023-12-08
1
导读:C++ 好用的序列化开源库 -- Cereal 使用说明

背景

序列化

开发者在编写应用程序时通常需要将程序的一些数据存储在内存中,然后将其写入文件或传输到另一台计算机上以实现通信。

这个将数据转化成能被存储并传输的格式的过程被称为“序列化”

Cereal

Cereal 是一个 C++11 的序列化库,它是现代、轻量级、快速和灵活的,可以用来保存和加载几乎所有类型的数据。

Cereal 支持将自定义数据类型序列化成 JSON、XML、二进制,反之也可以实现反序列化。

Cereal

概述

Cereal 库提供了一个高效,类型安全,易用,可扩展的解决方案,可用于各种复杂的应用场景。

基本特性

  • 类型安全:加载时类型不匹配会编译错误而非运行错误。
  • 可扩展:支持自定义序列化函数适用于各类和复杂类型。
  • 多格式支持:二进制、XML、JSON等格式可供选择。
  • 无侵入性:你无需修改类或者函数就能对其进行序列化。
  • 兼容性:易于管理版本迭代中数据结构的变化。

应用场景

数据持久化

数据持久化是将数据保存到硬盘上,后续加载使用的过程。例如,保存游戏状态和应用程序设置的需求。

网络通信

网络通信需要将数据序列化为可在网络上传输的格式,接收端进行反序列化以获取原始信息。

进程间通信

多进程间需要通过序列化数据传输,如管道、消息队列、共享内存等进程间通信机制。

数据库操作

许多情况下,数据被序列化并存储在数据库中,当需要读取时再进行反序列化操作。

Cereal 使用

下载与编译

Cereal GitHub 地址:https://github.com/USCiLab/cereal。

Cereal 是一个 head only 的库,无需编译。

基本使用

头文件引用

在项目设置中添加头文件引用:

序列化为二进制

把自定义对象序列化为二进制数据示例如下:

#include <iomanip>
#include <iostream>
#include <sstream>
#include <cereal/archives/binary.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>

struct demo_struct { //自定义结构体
    int id{};
    std::string name;
    std::vector<double> values;

    template<class Archive>
    void serialize(Archive& archive) // 序列化函数
    
{
        archive(id, name, values);
    }
};

int main() {
    demo_struct data; // 自定义对象
    data.id = 1;
    data.name = "Example";
    data.values = { 3.142.7181.414 };

    // 将结构体序列化为Binary字符串
    std::ostringstream oss(std::ios::binary);
    {
        cereal::BinaryOutputArchive   archive(oss);
        archive(data);
    }

    // 输出序列化后的Binary字符串到控制台
    std::string serializedData = oss.str();

    for (char byte : serializedData) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(byte)) << " ";
    }
    std::cout << std::endl;

    // 从Binary字符串反序列化结构体
    {
        demo_struct loaded_data;
        std::istringstream iss(oss.str());
        cereal::BinaryInputArchive  archive(iss);
        archive(loaded_data);

        // 显示反序列化后的数据
        std::cout << "\nLoaded ID: " << loaded_data.id << std::endl;
        std::cout << "Loaded Name: " << loaded_data.name << std::endl;
        std::cout << "Loaded Values: ";
        for (const auto& value : loaded_data.values) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

运行结果如下:

序列化为 Xml

把自定义对象序列化为 Xml 数据示例如下:

#include <iostream>
#include <sstream>
#include <cereal/archives/xml.hpp>
#include <cereal/types/vector.hpp>

struct demo_struct { //自定义结构体
    int id{};
    std::string name;
    std::vector<double> values;

    template<class Archive>
    void serialize(Archive& archive) // 序列化函数
 
{
        archive(id, name, values);
    }
};

int main() {
    demo_struct data; // 自定义对象
    data.id = 1;
    data.name = "Example";
    data.values = { 3.142.7181.414 };

    // 将结构体序列化为XML字符串
    std::ostringstream oss;
    {
        cereal::XMLOutputArchive archive(oss);
        archive(data);
    }

    // 输出序列化后的XML字符串到控制台
    std::cout << "序列化为 XML:\n" << oss.str() << std::endl;

    // 从XML字符串反序列化结构体
    {
        demo_struct loaded_data;
        std::istringstream iss(oss.str());
        cereal::XMLInputArchive archive(iss);
        archive(loaded_data);

        // 显示反序列化后的数据
        std::cout << "\nLoaded ID: " << loaded_data.id << std::endl;
        std::cout << "Loaded Name: " << loaded_data.name << std::endl;
        std::cout << "Loaded Values: ";
        for (const auto& value : loaded_data.values) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

运行结果:

序列号为 Json

把自定义对象序列化为 Json 数据示例如下:

#include <iostream>
#include <sstream>
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>


struct demo_struct { //自定义结构体
    int id{};
    std::string name;
    std::vector<double> values;

    template<class Archive>
    void serialize(Archive& archive) // 序列化函数
 
{
        archive(id, name, values);
    }
};

int main() {
    demo_struct data; // 自定义对象
    data.id = 1;
    data.name = "Example";
    data.values = { 3.142.7181.414 };

    // 将结构体序列化为JSON字符串
    std::ostringstream oss;
    {
        cereal::JSONOutputArchive  archive(oss);
        archive(data);
    }

    // 输出序列化后的JSON字符串到控制台
    std::cout << "序列化为 JSON:\n" << oss.str() << std::endl;

    // 从JSON字符串反序列化结构体
    {
        demo_struct loaded_data;
        std::istringstream iss(oss.str());
        cereal::JSONInputArchive  archive(iss);
        archive(loaded_data);

        // 显示反序列化后的数据
        std::cout << "\nLoaded ID: " << loaded_data.id << std::endl;
        std::cout << "Loaded Name: " << loaded_data.name << std::endl;
        std::cout << "Loaded Values: ";
        for (const auto& value : loaded_data.values) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

总结

任何涉及将内存中的数据结构转换为可以存储或传输的格式的场景,都可能需要使用序列化。

在简单的性能测试中,Cereal 通常比 Boost 的序列化库速度更快,而且产生的二进制形式占用更少的空间,尤其是针对更小的对象。


【声明】内容源于网络
0
0
国科慧安
关注安全与可靠性行业动态,提升国内安全与可靠性设计评价水平,打造尖端安全与可靠性软件,提供优质安全与可靠性设计评价服务。
内容 38
粉丝 0
国科慧安 关注安全与可靠性行业动态,提升国内安全与可靠性设计评价水平,打造尖端安全与可靠性软件,提供优质安全与可靠性设计评价服务。
总阅读15
粉丝0
内容38