一、前言
1、在编程中有时会有这样的需求:
- 保存内存中的对象到磁盘上,下次运行时直接读取该对象,不用再重新赋值,对于那些对象特别大,赋值时间长的对象来说能大大提高速度。比如我现在有一个存储着100万条数据的Map对象,如果把Map中的每条数据存入磁盘,然后再进行读取重新insert的话,这样耗时肯定很久;如果把Map对象直接保存到磁盘中,然后读取文件,读取出来不用重新insert,直接用,这样将会更方便
- 通过网络传输对象
2、序列化
能实现上面操作的方法叫做序列化:
序列化在计算机科学中通常有以下定义:
对同步控制而言,表示强制在同一时间内进行单一存取。
在数据储存与传送的部分是指将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等,或者透过网络传送资料时进行编码的过程,可以是字节或是XML等格式。而字节的或XML编码格式可以还原完全相等的对象。这程序被应用在不同应用程序之间传送对象,以及服务器将对象储存到档案或数据库。相反的过程又称为反序列化。
3、Boost Serialization
Boost 提供的序列化操作起来非常简单,先看一个非常简单的例子:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
struct employee
{
int id;
int age;
employee()
:id(0),age(0) {}
employee(int id_,int age_) :id(id_),age(age_) {}
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & id;
ar & age;
}
};
void save(const employee& es)
{
std::ofstream ofs("data");
boost::archive::text_oarchive oa(ofs);
oa << es;
}
void load(employee& es)
{
std::ifstream ifs("data");
boost::archive::text_iarchive ia(ifs);
ia >> es;
}
int main()
{
employee e1(10,20);
save(e1);
employee e2;
load(e2);
return 0;
}
这样e2就和e1相同了。
需要注意的是,自定义的结构或类中必须实现serialize方法,然后把需要保存的成员写在函数里。
除了可以保存自定义类型外,还可以保存STL中的各类容器,但是需要注意一点,因为需要实现serialize方法,所以引入的头文件不是STL的头文件,而是Booat实现的头文件。例如想保存vector对象,那么需要引入
#include < boost/serialization/vector.hpp >,其他类型同理。
其他
1、如果不想改变类中的函数,新增serialize函数,还可以采用这种
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, employee& g, const unsigned int version)
{
ar & g.id;
ar & g.age;
}
} // namespace serialization
}
2、如果自定义类型中含有位域的会,直接采用以上方法会出错,正确的方法如下
struct Test
{
char bits1 : 2;
char bits2 : 2;
char bits3 : 4;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
char tmp1 = bits1;
char tmp2 = bits2;
char tmp3 = bits3;
ar & BOOST_SERIALIZATION_NVP(tmp1);
ar & BOOST_SERIALIZATION_NVP(tmp2);
ar & BOOST_SERIALIZATION_NVP(tmp3);
bits1 = tmp1;
bits2 = tmp2;
bits3 = tmp3;
}
}