一提到序列化 反序列化, 很多人第一印象就是大名鼎鼎的google procotol buffer。但是运用PB,我们会遇到一些尴尬,PB只支持一些基本的数据类型。如果我要传输的是Map,List,Set等类型。我们就要额外的写一些函数做转换。对于这个问题,boost::serialization库可以很好的解决。
能够“Map进Map出”。
boost::serialization 基于 boost::archive 来完成任意复杂数据结构的序列化,boost::archive提供两个实现类来完成序列化、反序列化操作:
boost::archive::text_oarchive 序列化数据,也称为:输出、保存(save)
boost::archive::text_iarchive 反序列化数据,也称为:输入、载入(load)
也可以使用二进制格式:binary_oarchive, binary_iarchive
&操作符
序列化操作使用 << 或者 & 操作符将数据存入text_oarchive中:
反序列化操作使用 >> 或者 & 操作符从text_iarchive中读取数据:
为什么要引入&操作符?很简单,&操作符可以同时用于序列化和反序列化操作,这样就只需要提供一个 serialize 模板函数就可以同时用于两种操作,具体执行哪种由ar的类型(模版参数类型)决定;如果ar是text_oarchive类型则是序列化,如果ar是text_iarchive类型则是反序列化。
serialize模版函数
基础简单数据类型直接使用&操作符就行了,class类型数据需要自定义serialize模板函数来序列化对象,序列化时serialize函数会被自动调用。
有两种方式来给class添加serialize接口,一种是成员函数方式(intrusive),另一种是非成员函数方式(non-intrusive)。这两种方式各有利弊:non-intrusive方式虽然不用修改class的定义,但要求class数据成员的访问属性为public,不过可以通过声明函数为friend来解决这个问题。
成员函数方式(intrusive)
-
-
-
- class gps_position
- {
- private:
- friend class boost::serialization::access;
-
-
- template<class Archive>
- void serialize(Archive & ar, const unsigned int version)
- {
- ar & degrees & minutes & seconds;
- }
-
- int degrees;
- int minutes;
- float seconds;
-
- public:
- gps_position(){};
- gps_position(int d, int m, float s) :
- degrees(d), minutes(m), seconds(s)
- {}
- };
非成员函数方式(non-intrusive)
-
-
-
- class gps_position
- {
-
- template<class Archive>
- friend void serialize(Archive& ar, gps_position& g, const unsigned int version)
- {
- ar & g.degrees & g.minutes & g.seconds;
- }
-
-
- private:
- int degrees;
- int minutes;
- float seconds;
-
- public:
- gps_position(){};
- gps_position(int d, int m, float s) :
- degrees(d), minutes(m), seconds(s)
- {}
- };
类成员序列化
对类进行序列化要求所涉及的数据成员必须是可序列化的,即为:简单数据类型(POD)、数组类型、STL容器、或者实现了serialize接口的用户类。一个复合类类型实现了serialize接口后,就只需要将该类看做一个整体传给&操作符进行序列化,&操作符在序列化其数据成员时会自动调用相应的serialize接口进行处理。
-
-
-
- class bus_stop
- {
- friend class boost::serialization::access;
-
-
-
- template<class Archive>
- void serialize(Archive & ar, const unsigned int version)
- {
- ar & latitude & longitude;
- }
-
- gps_position latitude;
- gps_position longitude;
-
- protected:
- bus_stop(const gps_position & lat_, const gps_position & long_) :
- latitude(lat_), longitude(long_)
- {}
-
- public:
- bus_stop(){}
-
- virtual ~bus_stop(){}
- };
一个小例子来展示一下该库有多强大:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/set.hpp>
#include <sstream>
#include <iostream>
using namespace std;
using namespace boost::archive;
stringstream ss;
map<string, string> value;
string f1 = "f1", v1 = "v1", f2 = "f2", v2 ="v2", f3 = "f3", v3 = "v3";
void save()
{
text_oarchive oa(ss);
string test = "hello world ";
oa & test;
int i = 1;
oa & i;
value[f1]=v1;value[f2]=v2;value[f3]=v3;
oa & value;
}
void load()
{
text_iarchive ia(ss);
int i = 0;
string test;
map<string,string> value2;
ia & test & i & value2;
cout << test << i << endl;
map<string,string>::iterator it = value2.begin();
while (it != value2.end())
{
cout <<it->first <<": "<<it->second<<endl;
++it;
}
}
int main()
{
save();
load();
}
编译程序
编译程序时需要带上库:-lboost_serialization
参考:http://blog.csdn.net/liyongofdm/article/details/7650380