cereal:C++實現的開源序列化庫

閒來無事發現了一個基於C++實現的序列化工具,相比於其餘(好比Boost serialization或Google protobuf,恰巧都用過,之後再介紹),使用簡單,感受不錯,下面作個摸索。html

cereal介紹ios

cereal是一個開源的(BSD License)、輕量級的、支持C++11特性的、僅僅包含頭文件實現的、跨平臺的C++序列化庫。它能夠將任意的數據類型序列化成不一樣的表現形式,好比二進制、XML格式或JSON。cereal的設計目標是快速、輕量級、易擴展——它沒有外部的依賴關係,並且能夠很容易的和其餘代碼封裝在一塊或者單獨使用。c++

cereal支持標準庫的幾乎每個類型的序列化。cereal也徹底支持繼承和多態。因爲cereal被設計爲一個精簡、快速的庫,它不像其餘序列化庫(好比Boost)在同一層次上會進行對象跟蹤,這也致使了它不支持原始指針(raw pointer)和引用,可是智能指針(好比std::shared_ptr和std​​::unique_ptr)是沒有問題的。git

cereal適用於基於C++11標準的各類編譯器
cereal使用了一些C++11的新特性,所以須要一個兼容性更好的的C++編譯器才能正常工做。已被驗證可用的編譯器有g++4.7.三、clang++3.三、MSVC2013,或者更新版本。
它也可能能夠在老版本編譯器上工做,但並不保證徹底支持。當使用g++或clang++編譯器時,cereal同時須要libstdc++和libc++庫。
 
cereal:更快速,更好的壓縮
在簡單的性能測試中,cereal一般比Boost的序列化庫速度更快,並且產生的二進制形式佔用更少的空間,尤爲是針對更小的對象。cereal使用了C++中的速度最快的XMLJSON解析器和包裝器。
 
cereal是可擴展的
cereal提供了對標準庫的序列化支持,好比二進制的,XML和JSON序列化器。
cereal的源代碼相比Boost來說,更容易理解和擴展。 若是你須要別的東西,cereal能夠很容易地擴展,好比添加自定義序列化存檔或類型。github

cereal是易於使用的
在代碼增長cereal序列化功能能夠簡化爲包含一個頭文件,寫一個序列化函數。不管是從概念上仍是代碼層次上,cereal的功能都是自文檔化的。
若是你使用錯誤,cereal儘量的在編譯期觸發靜態斷言。json

對於Boost使用者來講,cereal提供了類似的語法,若是你使用過Boost的序列化庫,你會發現cereal的語法看起來很熟悉。api

若是你是從Boost轉向使用cereal,必定要閱讀這個過渡指南:http://uscilab.github.io/cereal/transition_from_boost.html函數

簡單的使用 工具

好吧,廢話就這麼多,先上一個簡單的事例:性能

std::ofstream os("my.xml");
cereal::XMLOutputArchive archive(os);
int age = 26;
std::string name = "lizheng";
archive(CEREAL_NVP(age), cereal::make_nvp("Name", name));

以上代碼完成了對一個int類型和string類型的xml序列化實現。結果以下:

<?xml version="1.0" encoding="utf-8"?>
<cereal>
    <age>26</age>
    <Name>lizheng</Name>
</cereal>

注意上面代碼中的cereal::XMLOutputArchive,其實還有針對JSON、二進制序列化的類,若是是序列化爲JSON串,結果以下(代碼在最下面):

{
    "age": 26,
    "Name": "lizheng"
}

個人Demo

完整代碼以下(或點此下載完整工程,或者從個人github下載包括cereal頭文件在內的整個項目):

  1 #include <iostream>
  2 #include <fstream>
  3 #include <string>
  4 #include "cereal/archives/binary.hpp"
  5 #include "cereal/archives/xml.hpp"
  6 #include "cereal/archives/json.hpp"
  7 #include "cereal/types/unordered_map.hpp"
  8 #include "cereal/types/memory.hpp"
  9 #include "cereal/types/string.hpp"  //必定要包含此文件,不然沒法將std::string序列化爲二進制形式,請看:https://github.com/USCiLab/cereal/issues/58
 10 
 11 using namespace std;
 12 
 13 struct MyRecord
 14 {
 15     int x, y;
 16     float z;
 17 
 18     template <class Archive>
 19     void serialize(Archive & ar)
 20     {
 21         ar(x, y, z);
 22     }
 23 
 24     friend std::ostream& operator<<(std::ostream& os, const MyRecord& mr);
 25 };
 26 
 27 std::ostream& operator<<(std::ostream& os, const MyRecord& mr)
 28 {
 29     os << "MyRecord(" << mr.x << ", " << mr.y << "," << mr.z << ")\n";
 30     return os;
 31 }
 32 
 33 struct SomeData
 34 {
 35     int32_t id;
 36     std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;
 37 
 38     SomeData(int32_t id_=0) : id(id_), data(new std::unordered_map<uint32_t, MyRecord>)
 39     {
 40         
 41     }
 42 
 43     template <class Archive>
 44     void save(Archive & ar) const
 45     {
 46         ar(id, data);
 47     }
 48 
 49     template <class Archive>
 50     void load(Archive & ar)
 51     {
 52         ar(id, data);
 53     }
 54 
 55     void push(uint32_t, const MyRecord& mr)
 56     {
 57         data->insert(std::make_pair(100, mr));
 58     }
 59 
 60     void print()
 61     {
 62         std::cout << "ID : " << id << "\n";
 63         if (data->empty())
 64             return;
 65         for (auto& item : *data)
 66         {
 67             std::cout << item.first << "\t" << item.second << "\n";
 68         }
 69     }
 70 };
 71 
 72 void Serialization_XML()
 73 {
 74     {
 75         std::ofstream os("my.xml");
 76 
 77         cereal::XMLOutputArchive archive(os);
 78 
 79         int age = 26;
 80         std::string name = "lizheng";
 81 
 82         //#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
 83         archive(CEREAL_NVP(age), cereal::make_nvp("Name", name));
 84 
 85         //os.close();  //注意:這裏不能顯示關閉ofstream,不然序列化沒法寫入到文件
 86     }
 87 
 88     {
 89         std::ifstream is("my.xml");
 90         cereal::XMLInputArchive archive(is);
 91 
 92         int age;
 93         std::string name;
 94 
 95         archive(age, name);
 96         std::cout << "Age: " << age << "\n" << "Name: " << name << "\n";
 97     }
 98 }
 99 
100 void Serialization_JSON()
101 {
102     {
103         std::ofstream os("my.json");
104         cereal::JSONOutputArchive archive(os);
105 
106         int age = 26;
107         std::string name = "lizheng";
108 
109         archive(CEREAL_NVP(age), cereal::make_nvp("Name", name));
110     }
111 
112     {
113         std::ifstream is("my.json");
114         cereal::JSONInputArchive archive(is);
115 
116         int age;
117         std::string name;
118 
119         archive(age, name);
120         std::cout << "Age: " << age << "\n" << "Name: " << name << "\n";
121     }
122 }
123 
124 
125 void Serialization_Binary()
126 {
127     {
128         std::ofstream os("my.binary", std::ios::binary);
129         cereal::BinaryOutputArchive archive(os);
130         
131         int age = 26;
132         std::string name = "lizheng";
133 
134         archive(CEREAL_NVP(age), CEREAL_NVP(name));
135     }
136     {
137         std::ifstream is("my.binary", std::ios::binary);
138         cereal::BinaryInputArchive archive(is);
139 
140         int age;
141         std::string name;
142 
143         archive(age, name);
144         std::cout << "Age: " << age << "\n" << "Name: " << name << "\n";
145     }
146 }
147 
148 void Serialization_Obj()
149 {
150     {
151         std::ofstream os("obj.cereal", std::ios::binary);
152         cereal::BinaryOutputArchive archive(os);
153 
154         MyRecord mr = { 1, 2, 3.0 };
155 
156         SomeData myData(1111);
157         myData.push(100, mr);
158     
159         archive(myData);
160     }
161     {
162         std::ifstream is("obj.cereal", std::ios::binary);
163         cereal::BinaryInputArchive archive(is);
164 
165         SomeData myData;
166         archive(myData);
167         myData.print();
168     }
169 }
170 
171 
172 int main()
173 {
174     Serialization_XML();     std::cout << "----------------------\n";
175 
176     Serialization_JSON();    std::cout << "----------------------\n";
177 
178     Serialization_Binary();  std::cout << "----------------------\n";
179 
180     Serialization_Obj();     std::cout << "----------------------\n";
181 
182     getchar();
183     return 0;
184 }
相關文章
相關標籤/搜索