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!