cereal庫實現序列化和反序列化

cereal簡介

cereal是一個基於c++實現的序列化工具庫,用於將c++的各種數據結構序列化成二進制流進行傳輸,並將二進制流反序列化成原來的數據結構。相比同用途庫,cereal使用簡單,僅需包含頭文件,運行效率尚可,對比如下:

cereal的下載和安裝

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

編譯源碼過程很簡單,在此不詳述(注意源碼解壓在全英文路徑下進行編譯,不然出現編譯失敗的錯誤)。

使用cmake工具對源碼進行編譯和安裝,選擇對應版本的編譯器和x86/x64選項,最終釋放出一系列頭文件到安裝路徑:

將cereal文件夾拷貝到指定位置,並設置系統環境變量爲頭文件所在路徑,如:"D:\3rdLib\cereal\include"。

接下來就可以使用cereal庫了~

cereal庫的使用

cereal庫的使用需要注意以下幾點:

  • 需要人工保證讀寫的archive版本相對應。
  • 二進制存檔可以通過包含<cereal/archives/二進制.hpp>來使用,二進制歸檔不嘗試確保在不同的體系結構之間保持endianness。如果您的數據將在小端和大端機器上讀取,您應該使用<cereal/archives/portable_binary。hpp>,它跟蹤保存和加載機器的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 <cereal/access.hpp>
#include <cereal/access.hpp>
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 <fstream>
#include <iostream>
#include <cstdlib>
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<double> vecdata;

    // 下面的操作是爲了在xml文件寫入節點名字.
    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(CEREAL_NVP(templatePageNum));
        ar(CEREAL_NVP(vecdata));
    }

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

    //template<class Archive>
    //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()=
<?xml version="1.0" encoding="utf-8"?>
<cereal>
        <value0>
                <templatePageNum>41</templatePageNum>
                <vecdata size="dynamic">
                        <value0>35</value0>
                        <value1>190</value1>
                        <value2>900</value2>
                        <value3>737</value3>
                        <value4>364</value4>
                </vecdata>
        </value0>
</cereal>


strbuf1=

strbuf1=
<?xml version="1.0" encoding="utf-8"?>
<cereal>
        <value0>
                <templatePageNum>41</templatePageNum>
                <vecdata size="dynamic">
                        <value0>35</value0>
                        <value1>190</value1>
                        <value2>900</value2>
                        <value3>737</value3>
                        <value4>364</value4>
                </vecdata>
        </value0>
</cereal>


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!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章