对象序列化是项目中最经常看到的场景,因此实现该功能的库也有很多,如:thrift、protobuf、avro,但我觉得这些库都太过沉重,因为他们还提供了rpc的功能,如果只是单纯做对象序列化,boost serialization是个不错的选择,以下boost serialization简称BS。
一、代码目录
1.$BOOST_HOME/archive存档方式类目录
类型 | 普通字节 | 宽字节 |
---|---|---|
二进制 | binary_iarchive.hpp binary_oarchive.hpp | binary_wiarchive.hpp binary_woarchive.hpp |
文本 | text_iarchive.hpp text_oarchive.hpp | text_wiarchive.hpp text_woarchive.hpp |
xml | xml_iarchive.hpp xml_oarchive.hpp | xml_wiarchive.hpp xml_woarchive.hpp |
2.$BOOST_HOME/serialization 序列化数据类型目录
目前BS基本上几乎支持了所有的C++数据类型,还包括指针、数组等,并且也支持了stl的容器,但要包含相关头文件。
vector.hpp支持vector的序列化
list.hpp支持list的序列化
deque.hpp支持deque的序列化
map.hpp支持map的序列化
hash_map.hpp支持hash_map的序列化
等等...
除了stl的容器,也支持boost的相关容器,如array.hpp
二、序列化类实现
1.置入式实现
#include <fstream>
// 文本方式存档
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
/
// gps coordinate
//
// illustrates serialization for a simple type
//
class gps_position
{
private:
friend class boost::serialization::access;//置入式
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & degrees;//序列化或反序列化&操作符比>>和<<更为方便
ar & minutes;
ar & seconds;
}
int degrees;
int minutes;
float seconds;
public:
gps_position(){};
gps_position(int d, int m, float s) :
degrees(d), minutes(m), seconds(s)
{}
};
int main() {
std::fstream ofs("filename");
// create class instance
const gps_position g(35, 59, 24.567f);
// save data to archive
{
boost::archive::text_oarchive oa(ofs);
oa << g;
}
// ... some time later restore the class instance to its orginal state
gps_position newg;
{
std::fstream ifs("filename");
boost::archive::text_iarchive ia(ifs);
ia >> newg;
}
return 0;
}
2.非置入实现
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
class gps_position
{
public:
int degrees;
int minutes;
float seconds;
gps_position(){};
gps_position(int d, int m, float s) :
degrees(d), minutes(m), seconds(s)
{}
};
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, gps_position & g, const unsigned int version)//必须包含在boost::serialization名字空间下
{
ar & g.degrees;
ar & g.minutes;
ar & g.seconds;
}
} // namespace serialization
} // namespace boost
3.可以序列化类对象,但被序列化的类必须实现序列化函数
class bus_stop
{
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & latitude;
ar & 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(){}
// See item # 14 in Effective C++ by Scott Meyers.
// re non-virtual destructors in base classes.
virtual ~bus_stop(){}
};
4.继承关系的序列化
#include <boost/serialization/base_object.hpp>//必须包含这个头文件
class bus_stop_corner : public bus_stop
{
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// serialize base class information
ar & boost::serialization::base_object<bus_stop>(*this);//序列化基类
ar & street1;
ar & street2;
}
std::string street1;
std::string street2;
virtual std::string description() const
{
return street1 + " and " + street2;
}
public:
bus_stop_corner(){}
bus_stop_corner(const gps_position & lat_, const gps_position & long_,
const std::string & s1_, const std::string & s2_
) :
bus_stop(lat_, long_), street1(s1_), street2(s2_)
{}
};
5.序列化数组
class bus_route
{
friend class boost::serialization::access;
bus_stop stops[10];
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & stops;//会自动在前面加上数组的长度
}
public:
bus_route(){}
};
6.序列化stl容器
#include <boost/serialization/list.hpp>
class bus_route
{
friend class boost::serialization::access;
std::list<bus_stop> stops;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & stops;//会自动加上容器的长度
}
public:
bus_route(){}
};
7.可根据版本号序列化
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/version.hpp> //必须包含这个头文件
class bus_route
{
friend class boost::serialization::access;
std::list<bus_stop> stops;
std::string driver_name;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// only save/load driver_name for newer archives
if(version > 0)//根据版本号序列化
ar & driver_name;
ar & stops;
}
public:
bus_route(){}
};
BOOST_CLASS_VERSION(bus_route, 1) //定义version=1
8.读写分离
一直以来都是serialize这个函数做序列化很反序列化,但有时候序列化和反序列化的方法不一致,serialize函数就难以支持了,因此要用save/load函数,save做序列化操作,而load做反序列化操作。
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/split_member.hpp>
class bus_route
{
friend class boost::serialization::access;
std::list<bus_stop> stops;
std::string driver_name;
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
// note, version is always the latest when saving
ar & driver_name;
ar & stops;
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
if(version > 0)
ar & driver_name;
ar & stops;
}
BOOST_SERIALIZATION_SPLIT_MEMBER() //这个宏定义必须要在类中加上
public:
bus_route(){}
};
BOOST_CLASS_VERSION(bus_route, 1)