cereal库实现序列化和反序列化

cereal简介

cereal是一个基于c++实现的序列化工具库,用于将c++的各种数据结构序列化成二进制流进行传输,并将二进制流反序列化成原来的数据结构。相比同用途库,cereal使用简单,仅需包含头文件,运行效率尚可,对比如下:

cereal库实现序列化和反序列化_第1张图片

cereal的下载和安装

cereal的官方下载地址为:http://uscilab.github.io/cereal/index.html

编译源码过程很简单,在此不详述(注意源码解压在全英文路径下进行编译,不然出现编译失败的错误)。

使用cmake工具对源码进行编译和安装,选择对应版本的编译器和x86/x64选项,最终释放出一系列头文件到安装路径:

cereal库实现序列化和反序列化_第2张图片

将cereal文件夹拷贝到指定位置,并设置系统环境变量为头文件所在路径,如:"D:\3rdLib\cereal\include"。

接下来就可以使用cereal库了~

cereal库的使用

cereal库的使用需要注意以下几点:

  • 需要人工保证读写的archive版本相对应。
  • 二进制存档可以通过包含来使用,二进制归档不尝试确保在不同的体系结构之间保持endianness。如果您的数据将在小端和大端机器上读取,您应该使用,它跟踪保存和加载机器的endianness,并适当地转换数据。它的开销略高于常规的二进制存档。记住在构造流时指定二进制标志(std::ios::binary)。
  • 在序列化每种类型之前和之后立即调用特殊函数,称为prologue and epilogue。
  • 没有默认构造函数的类用loadAndConstruct
  • 序列化函数:可以是类内部函数也可以是外部函数。既可以使用单独的序列化函数,也可以分开使用load和save或load_minimal和save_minimal对(例如,在加载类时动态分配内存),无需显示的告诉cereal,但是需要只使用其中一种。
    • 注:save函数是const的
    • 如果需要把serialize函数写成protected或者private,需要声明友元friend class cereal::access;,并包含头文件#include
#include 
template
void serialize(Archive & archive)//, const std::uint32_t /* version */); template
{
    archive(mtl_file_name);
    archive(mat4);
}
  • 所有的STL类型都要相应的加上cereal/types/xxx.hpp的头文件,基础类型用cereal/types/base_class.hpp
  • static成员要加details/static_object.hpp

————————————————
版权声明:本文为CSDN博主「_Lina」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_24634505/article/details/89534314

我分别测试了将一个结构体变量序列化成binary,xml和json的文件流和string流,并从文件流和string流中反序列化成原结构体变量,测试代码如下:

#include "cereal/archives/xml.hpp"
#include "cereal/archives/binary.hpp"
#include "cereal/archives/json.hpp"
#include "cereal/types/memory.hpp"
#include "cereal/types/base_class.hpp"
#include "cereal/types/vector.hpp"
#include 
#include 
#include 
using namespace std;

typedef struct STRUCT_CEREAL
{
    STRUCT_CEREAL()
    {
        templatePageNum = rand();
        vecdata.push_back(rand() % 1024);
        vecdata.push_back(rand() % 1024);
        vecdata.push_back(rand() % 1024);
        vecdata.push_back(rand() % 1024);
        vecdata.push_back(rand() % 1024);
    }

    size_t templatePageNum;
    vector vecdata;

    // 下面的操作是为了在xml文件写入节点名字.
    template 
    void serialize(Archive & ar)
    {
        ar(CEREAL_NVP(templatePageNum));
        ar(CEREAL_NVP(vecdata));
    }

    //template
    //void save(Archive & archive) const
    //{
    //    cout << "save" << endl;
    //    archive(templatePageNum);
    //    archive(vecdata);
    //}

    //template
    //void load(Archive & archive)
    //{
    //    cout << "load" << endl;
    //    archive(templatePageNum);
    //    //archive(vecdata);
    //}

}STRUCT_CEREAL;

ostream& operator<<(ostream& o, STRUCT_CEREAL& obj)
{
    o << "templatePageNum=" << obj.templatePageNum << endl
        << "vecdata=\n";
    for (size_t i = 0; i < obj.vecdata.size(); i++)
    {
        o << "vecdata[" << i << "]=" << obj.vecdata[i] << endl;
    }
    return o;
}

void test_cereal()
{

    STRUCT_CEREAL stData;
    cout << stData << endl;


    /// binary.
    // output to file.
    ofstream out0;
    {
        out0.open("out.cereal", std::ios::binary);
        cereal::BinaryOutputArchive archive(out0);
        archive(stData);
    }
    out0.close();

    STRUCT_CEREAL ttt0;
    ifstream in0;
    {
        in0.open("out.cereal", ios::in);
        cereal::BinaryInputArchive archive(in0);
        archive(ttt0);
    }
    in0.close();
    cout << ttt0 << endl;

    // output to memory.
    string strbuf0;
    ostringstream outs0;
    {
        cereal::BinaryOutputArchive archive(outs0);
        archive(stData);
    }
    cout << "outs0.str()=" << endl << outs0.str() << endl;
    cout << "strbuf0=" << endl << strbuf0 << endl;
    strbuf0 = outs0.str();
    outs0.clear();
    cout << "strbuf0=" << endl << strbuf0 << endl;

    STRUCT_CEREAL ttts0;
    string strbuff00;
    istringstream ins0(strbuf0);
    {
        cereal::BinaryInputArchive archive(ins0);
        archive(ttts0);
    }
    cout << "ttts0=" << endl << ttts0 << endl;

    /// xml.
    ofstream out1;
    {
        out1.open("./out.xml", ios::trunc); //ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建
        cereal::XMLOutputArchive archive(out1);
        archive(stData);
    }
    out1.close();


    ifstream in1;
    STRUCT_CEREAL ttt1;
    {
        in1.open("./out.xml", ios::in);
        cereal::XMLInputArchive archive(in1);
        archive(ttt1);
    }
    in1.close();
    cout << ttt1 << endl;

    // output to memory.
    string strbuf1;
    ostringstream outs1;
    {
        cereal::XMLOutputArchive archive(outs1);
        archive(stData);
    }
    cout << "outs1.str()=" << endl << outs1.str() << endl;
    cout << "strbuf1=" << endl << strbuf1 << endl;
    strbuf1 = outs1.str();
    outs1.clear();
    cout << "strbuf1=" << endl << strbuf1 << endl;

    STRUCT_CEREAL ttts1;
    string strbuff11;
    istringstream ins1(strbuf1);
    {
        cereal::XMLInputArchive archive(ins1);
        archive(ttts1);
    }
    cout << "ttts1=" << endl << ttts1 << endl;


    /// json.
    ofstream out2;
    {
        out2.open("./out.json", ios::trunc); //ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建
        cereal::JSONOutputArchive archive(out2);
        archive(stData);
    }
    out2.close();


    ifstream in2;
    STRUCT_CEREAL ttt2;
    {
        in2.open("./out.json", ios::in);
        cereal::JSONInputArchive archive(in2);
        archive(ttt2);
    }
    in2.close();
    cout << ttt2 << endl;


    // output to memory.
    string strbuf2;
    ostringstream outs2;
    {
        cereal::JSONOutputArchive archive(outs2);
        archive(stData);
    }
    cout << "outs2.str()=" << endl << outs2.str() << endl;
    cout << "strbuf2=" << endl << strbuf2 << endl;
    strbuf2 = outs2.str();
    outs2.clear();
    cout << "strbuf2=" << endl << strbuf2 << endl;

    STRUCT_CEREAL ttts2;
    string strbuff22;
    istringstream ins2(strbuf2);
    {
        cereal::JSONInputArchive archive(ins2);
        archive(ttts2);
    }
    cout << "ttts2=" << endl << ttts2 << endl;
    
    cout << "running cereal finished!" << endl;
}

运行结果如下:

templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

outs0.str()=
)                   €A@     纆@      孈   嘆     纕@
strbuf0=

strbuf0=
)                   €A@     纆@      孈   嘆     纕@
ttts0=
templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

outs1.str()=


        
                41
                
                        35
                        190
                        900
                        737
                        364
                
        



strbuf1=

strbuf1=


        
                41
                
                        35
                        190
                        900
                        737
                        364
                
        



ttts1=
templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

outs2.str()=
{
    "value0": {
        "templatePageNum": 41,
        "vecdata": [
            35.0,
            190.0,
            900.0,
            737.0,
            364.0
        ]
    }
}
strbuf2=

strbuf2=
{
    "value0": {
        "templatePageNum": 41,
        "vecdata": [
            35.0,
            190.0,
            900.0,
            737.0,
            364.0
        ]
    }
}
ttts2=
templatePageNum=41
vecdata=
vecdata[0]=35
vecdata[1]=190
vecdata[2]=900
vecdata[3]=737
vecdata[4]=364

running cereal finished!

 

你可能感兴趣的:(C/C++,序列化,cereal,c++序列化工具)