只知道google protocol buffer?Boost serialize 可以更好解决STL序列化 反序列化 附小例子

一提到序列化 反序列化, 很多人第一印象就是大名鼎鼎的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中:

ar  <<  data;
ar 
&  data;

 

反序列化操作使用 >> 或者 & 操作符从text_iarchive中读取数据:

ar  >>  data;
ar 
&  data;

为什么要引入&操作符?很简单,&操作符可以同时用于序列化和反序列化操作,这样就只需要提供一个 serialize 模板函数就可以同时用于两种操作,具体执行哪种由ar的类型(模版参数类型)决定;如果ar是text_oarchive类型则是序列化,如果ar是text_iarchive类型则是反序列化。

 

serialize模版函数 

基础简单数据类型直接使用&操作符就行了,class类型数据需要自定义serialize模板函数来序列化对象,序列化时serialize函数会被自动调用。

 

有两种方式来给class添加serialize接口,一种是成员函数方式(intrusive),另一种是非成员函数方式(non-intrusive)。这两种方式各有利弊:non-intrusive方式虽然不用修改class的定义,但要求class数据成员的访问属性为public,不过可以通过声明函数为friend来解决这个问题。

 

 成员函数方式(intrusive)

  1. /** 
  2.  * GPS坐标点 
  3.  */  
  4.  class gps_position  
  5.  {  
  6.  private:  
  7.      friend class boost::serialization::access;  
  8.        
  9.      //intrusive方式,该成员函数同时用于序列化和反序列化操作  
  10.      template<class Archive>  
  11.      void serialize(Archive & ar, const unsigned int version)  
  12.      {  
  13.          ar & degrees & minutes & seconds;  
  14.      }  
  15.    
  16.      int degrees;  
  17.      int minutes;  
  18.      float seconds;  
  19.    
  20.  public:  
  21.      gps_position(){};  
  22.      gps_position(int d, int m, float s) :  
  23.          degrees(d), minutes(m), seconds(s)  
  24.      {}  
  25.  };  


 

非成员函数方式(non-intrusive) 

  1. /** 
  2.  * GPS坐标点 
  3.  */  
  4.  class gps_position  
  5.  {  
  6.      //non-intrusive方式,定义友元模版函数  
  7.      template<class Archive>  
  8.      friend void serialize(Archive& ar, gps_position& g, const unsigned int version)  
  9.      {  
  10.          ar & g.degrees & g.minutes & g.seconds;  
  11.      }  
  12.    
  13.    
  14.  private:  
  15.      int degrees;  
  16.      int minutes;  
  17.      float seconds;  
  18.    
  19.  public:  
  20.      gps_position(){};  
  21.      gps_position(int d, int m, float s) :  
  22.          degrees(d), minutes(m), seconds(s)  
  23.      {}  
  24.  };  


 

 类成员序列化

 对类进行序列化要求所涉及的数据成员必须是可序列化的,即为:简单数据类型(POD)、数组类型、STL容器、或者实现了serialize接口的用户类。一个复合类类型实现了serialize接口后,就只需要将该类看做一个整体传给&操作符进行序列化,&操作符在序列化其数据成员时会自动调用相应的serialize接口进行处理。

  1. /** 
  2.  * bus_stop类 
  3.  */  
  4.  class bus_stop  
  5.  {  
  6.      friend class boost::serialization::access;  
  7.    
  8.      //只要数据成员类型是可序列化的就可以使用&操作符进行处理  
  9.      //可序列化的类型包括:基础的简单数据类型、数组类型、STL容器、或者实现了serialize接口的类  
  10.      template<class Archive>  
  11.      void serialize(Archive & ar, const unsigned int version)  
  12.      {  
  13.          ar & latitude & longitude;  
  14.      }  
  15.    
  16.      gps_position latitude;        //serializable members  
  17.      gps_position longitude;  
  18.    
  19.  protected:  
  20.      bus_stop(const gps_position & lat_, const gps_position & long_) :  
  21.      latitude(lat_), longitude(long_)  
  22.      {}  
  23.    
  24.  public:  
  25.      bus_stop(){}  
  26.        
  27.      virtual ~bus_stop(){}  
  28.  };  

一个小例子来展示一下该库有多强大:
#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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值