boost--序列化库serialization
序列化可以把对象转化成一个字节流存储或者传输,在需要时再回复成与原始状态一致的等价对象。C++标准没有定义这个功能。boost.serialization以库的形式提供了这个功能,非常强大,可以序列化C++中各种类型,而且简单易用。
boost.serialization库必须编译后才能使用。有关boost库的编译可以参考之前的文章windows下编译和安装boost库.
serialization库把存档和类型的序列化完全分离开来,任意的数据类型都可以采用任意格式的存档保存。所以头文件被分别放在了两个目录下:
<boost/archive/>
目录的头文件处理序列化的存档表现形式
<boost/serialization>
目录里的头文件提供对各种数据类型的序列化能力。
boost.serialization库位于名称空间boost.archive
,在使用时必须根据需要包含特定的存档头文件和序列化头文件。
例如:
#include <boost/archive/text_oarchive.hpp> //文本格式输入存档
#include <boost/archive/text_iarchive.hpp> //文本格式输出存档
#include <boost/serialization/vector.hpp> //vector的序列化实现头文件
using namespace boost:archive;//打开名称空间
serialization库的三个基本概念:
存档
存档在serialization库中表现为一系列的字节(不一定是ASCII或者二进制),它对应任意的C++对象,可以持久化保存并在某个时刻恢复成C++对象。
根据存档格式分为:
纯文本格式 text_iarchive
text_oarchive
xml格式 xml_iarchive
xml_oarchive
二进制格式 binary_iarchive
binary_oarchive
根据输入输出存档方向:
输出存档(saving) : 把C++对象序列化为某种格式的字节流
输入存档(loading) : 把某种格式的字节流反序列化为等价的C++对象。
可序列化
只有可序列化的C++类型才能够被序列化为字节流,保存到存档中或这从存档中恢复。
(1) C++基本类型都是可序列化的,如bool、int、double、enum。
(2) 字符串string、wstring是可序列化的
(3) 自定义类型如果有特定形式的成员函数或者自由函数serialize()也是可序列化的。
(4) 可序列化类型的数组也是可序列化的。
(5) 可序列化类型的指针和引用也是可序列化的。
注:serialization库支持标准库里定义的complex
bitset
valarray
pair
等
对标准容器支持,包括vector、deque、list、set、map,不支持stack,queue,priority_queue.
序列化和反序列化
序列化和反序列化是两个互逆的过程。
序列化操作符: operator<<
operator&
反序列化操作符: operator>>
operator&
使用序列化
//序列化
ofstream ofs("serial.txt"); //输出文件流
string str("boost serializaiton");
{
boost::archive::text_oarchive oa(ofs);//文本输出存档连接到文件流
oa & str; //序列化到输出存档
}
//反序列化
ifstream ifs("serial.txt");//文件输入流
string istr;
{
boost::archive::text_iarchive ia(ifs); //文本输入存档连接到文件流
ia & istr;//从输入文档反序列化
}
assert(istr == str);
输出存档(如:text_oarchive
)的构造函数需要使用一个输出流,创建输出存档后,就可以使用operator<<
或operator&
向存档写入对象。
输如存档(如:text_iarchive
)构造时要求使用一个输入流,使用operator<<
和operator&
执行反序列化。
一个简单的序列化操作模版类:
//BoostArchive.h
#ifndef _BOOST_ARCHIVE_H_
#define _BOOST_ARCHIVE_H_
#include <list>
#include <fstream>
#include <string>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
using std::list;
using std::ifstream;
using std::ofstream;
using std::string;
template <class T>
class BoostArchive
{
public:
typedef T entity_type;
typedef boost::archive::text_iarchive InputArchive;
typedef boost::archive::text_oarchive OutputArchive;
BoostArchive(const string & archive_file_path)
: _file_path_name(archive_file_path)
, _p_ofs(NULL)
, _p_output_archive(NULL)
, _entity_nums(0)
{
load_arvhive_info();
}
~BoostArchive()
{
close_output();
}
//存储一个对象,序列化
void store(const entity_type & entity);
//反序列化, 提取所有对象
bool restore(list<entity_type> & entitys);
size_t size() const
{
return _entity_nums;
}
private:
void save_archive_info() //保存已序列化的对象个数信息
{
ofstream ofs;
ofs.open(get_archive_info_file_path(),std::ios::out | std::ios::trunc);
if (ofs.is_open())
{
ofs << _entity_nums;
}
ofs.close();
}
void load_arvhive_info()//读取已序列化的对象个数信息
{
ifstream ifs;
ifs.open(get_archive_info_file_path(),std::ios_base::in);
if (ifs.is_open() && !ifs.eof())
{
int enity_num = 0;
ifs >> enity_num;
_entity_nums = enity_num;
}
ifs.close();
}
string get_archive_info_file_path()
{
return "boost_archive_info.meta";
}
void close_output()
{
if (NULL != _p_output_archive)
{
delete _p_output_archive;
_p_output_archive = NULL;
save_archive_info();
}
if (NULL != _p_ofs)
{
delete _p_ofs;
_p_ofs = NULL;
}
}
private:
size_t _entity_nums;
string _file_path_name;
ofstream * _p_ofs;
OutputArchive * _p_output_archive;
};
template <class T>
bool BoostArchive<T>::restore( list<entity_type> & entitys )
{
close_output();
load_arvhive_info();
ifstream ifs(_file_path_name);
if (ifs)
{
InputArchive ia(ifs);
for (size_t cnt = 0; cnt < _entity_nums; ++cnt)
{
entity_type entity;
ia & entity;
entitys.push_back(entity);
}
return true;
}
return false;
}
template <class T>
void BoostArchive<T>::store( const entity_type & entity )
{
if (NULL == _p_output_archive)
{
_p_ofs = new ofstream(_file_path_name);
_p_output_archive = new OutputArchive(*_p_ofs);
}
(*_p_output_archive) & entity;
++_entity_nums;
}
#endif
自定义类型的序列化
自定义类型可以使用两种方式实现可序列化:侵入式和非侵入式
侵入式可序列化
侵入式方式要求类必须实现如下形式的一个成员函数serialize():
template<typename Archive>
void serialize(Archive & ar, const unsigned int version)
{
...
}
第一个参数是被用于序列化或反序列化的存档,第二个参数是一个整型的版本号。在serialize函数内部,应当使用operator&
存取类的所有必要的数据成员。
boost::serialization::access
是一个辅助类,声明了一系列的静态成员函数间接调用自定义类的serialize(),存档通过它来完成对自定义类的序列化。一般在自定义类中声明boost::serialization::access
为友元来授予访问权限,serialize()
设置为private。
侵入式序列化示例:
//自定义类型的序列化
//侵入式
class Student
{
public:
Student()
: _id(-1)
, _name("")
{}
Student(const int id, const string & name)
: _id(id)
, _name(name)
{}
void add_score(double score)
{
_scores.push_back(score);
}
double get_avg_score() const
{
return (_scores.size() == 0) ? 0 :
(std::accumulate(_scores.begin(),_scores.end(),0) / _scores.size());
}
string get_student_msg() const
{
stringstream ss;
ss << "\nID: " << _id << " NAME: " << _name << "\n";
for (auto iter = _scores.begin(); iter != _scores.end(); ++iter)
{
ss << *iter << " ";
}
ss << "\nAVG_SCORE: " << get_avg_score();
return ss.str();
}
private:
friend boost::serialization::access; //声明友元,授予访问权限
template<typename Archive>
void serialize(Archive & ar, const unsigned int version) //序列化函数
{
ar & _id;
ar & _name;
ar & _scores;
}
private:
string _name;
int _id;
vector<double> _scores;
};
测试代码(使用到了上面的辅助类BoostArchive):
void TestArchive()
{
Student s1(1,"cm");
s1.add_score(100);
s1.add_score(80);
s1.add_score(90);
Student s2(2,"cj");
s2.add_score(100);
s2.add_score(90);
s2.add_score(90);
Student s3(3,"zj");
s3.add_score(100);
s3.add_score(60);
s3.add_score(90);
string archive_file_name("students.dat");
BoostArchive<Student> archive(archive_file_name);
archive.store(s1); //序列化
archive.store(s2);
archive.store(s3);
list<Student> list1;
archive.restore(list1); //反序列化,恢复数据
for (auto iter = list1.cbegin(); iter != list1.end(); ++iter)
{
cout << iter->get_student_msg();
}
}
非侵入式可序列化
侵入式可序列化的缺点是要修改类定义,添加一些代码。如果某个类定义是无法修改的,就只能使用非侵入的方式,定义一个如下形式的自由函数:
//非侵入式
namespace boost{
namespace serialization{
template<typename Archive>
void serialize(Archive & ar, some_class & t, const unsigned int version)
{
...
}
}
}
自由函数serialize()与成员函数serialize类似,多了一个自定义类型的参数t,在函数体内用它来完成序列化和反序列化。因为非侵入式不能访问类的私有成员,所以要求要被序列化的成员为public。
其次为了方便编译器查找自由函数serialize,通常应该定义在名称空间boost::serialization
,或boost::archive
和自定义类型所在的名称空间。
非侵入式序列化示例:
struct Person
{
Person()
:_id(-1)
, _name("")
{
}
Person(int id, const string & name)
:_id(id)
, _name(name)
{
}
string get_msg() const
{
stringstream ss;
ss << _id << " " << _name;
return ss.str();
}
int _id;
string _name;
};
//非侵入式
namespace boost{
namespace serialization{
template<typename Archive>
void serialize(Archive & ar, Person & p, const unsigned int version)
{
ar & p._id;
ar & p._name;
}
}
boost--序列化库serialization的更多相关文章
- 【boost】使用serialization库序列化子类
boost.serialization库是一个非常强大又易用的序列化库,用于对象的保存与持久化等. 使用base_object可以在序列化子类的同时也序列化父类,以此获得足够的信息来从文件或网络数据中 ...
- cereal:C++实现的开源序列化库
闲来无事发现了一个基于C++实现的序列化工具,相比于其他(比如Boost serialization或Google protobuf,恰巧都用过,以后再介绍),使用简单,感觉不错,下面做个摸索. ce ...
- C++序列化库的实现
C++中经常需要用到序列化与反序列化功能,由于C++标准中没有提供此功能,于是就出现了各式各样的序列化库,如boost中的,如谷歌的开源项目,但是很多库都依赖其他库过于严重,导致库变得很庞大.今天来分 ...
- Boost C++ 库 中文教程(全)
Boost C++ 库 目录 第 1 章 简介 第 2 章 智能指针 第 3 章 函数对象 第 4 章 事件处理 第 5 章 字符串处理 第 6 章 多线程 第 7 章 异步输入输出 第 8 章 进程 ...
- 性能超四倍的高性能.NET二进制序列化库
二进制序列化在.NET中有很多使用场景,如我们使用分布式缓存时,通常将缓存对象序列化为二进制数据进行缓存,在ASP.NET中,很多中间件(如认证等)也都是用了二进制序列化. 在.NET中我们通常使用S ...
- 如何在WINDOWS下编译BOOST C++库 .
如何在WINDOWS下编译BOOST C++库 cheungmine 2008-6-25 写出来,怕自己以后忘记了,也为初学者参考.使用VC8.0和boost1.35.0. 1)下载boost ...
- Windows下如何使用BOOST C++库 .
Windows下如何使用BOOST C++库 我采用的是VC8.0和boost_1_35_0.自己重新编译boost当然可以,但是我使用了 http://www.boostpro.com/produc ...
- Boost线程库学习笔记
一.创建一个线程 创建线程 boost::thread myThread(threadFun); 需要注意的是:参数可以是函数对象或者函数指针.并且这个函数无参数,并返回void类型. 当一个thre ...
- Boost正则表达式库regex常用search和match示例 - 编程语言 - 开发者第2241727个问答
Boost正则表达式库regex常用search和match示例 - 编程语言 - 开发者第2241727个问答 Boost正则表达式库regex常用search和match示例 发表回复 Boo ...
随机推荐
- Java 反编译工具 —— JAD 的下载地址(Windows版/Linux版/Mac OS 版)
Java 反编译工具 —— JAD 的下载地址. 各种版本哦! Windows版,Linux版,Mac OS 版,等等 下载地址: http://varaneckas.com/jad/
- CSS技巧:逐帧动画抖动解决方案
笔者所在的前端团队主要从事移动端的H5页面开发,而团队使用的适配方案是: viewport units + rem.具体可以参见凹凸实验室的文章 – 利用视口单位实现适配布局 . 笔者目前(2017. ...
- 阿里云ubuntu14.4上部署gogs
以前曾经在centos上部署了gitlab,但因为买的配置比较低,实际效果并不理想,经常卡机.而且,gitlab配置相当麻烦,需要依赖很多被墙包支持.最近在用golang搞开发,顺道发现了gogs这款 ...
- C语言程序设计--宏和预处理
C语言宏 宏定义常量 #include <stdio.h> #define SIZE 100 #define BANNER "WARNING:" int main(vo ...
- Metrics.Net构建指标监控中心
Metrics.NET(https://github.com/etishor/Metrics.NET)是一个给CLR 提供度量工具的包,它是移植自Java的metrics,支持的平台 .NET 4.5 ...
- cadence allegro 封装产考原点修改
打开 dra文件后 在菜单栏 setup - change drawing origin 在命令栏输入 新的参考点位置 如想更改新坐标位置为 1,2 .输入 x 1 2 上面两步操作后即可修改!
- 【CF708E】Student's Camp 组合数+动态规划
[CF708E]Student's Camp 题意:有一个n*m的网格,每一秒钟,所有左面没有格子的格子会有p的概率消失,右面没有格子的格子也会有p的概率消失,问你t秒钟后,整个网格的上边界和下边界仍 ...
- dhroid - ioc基础(@Inject*)
1 ioc即控制反转.控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心.控制反转还有一 ...
- 玩node-images模块---Node.js轻量级跨平台图像编解码库
Node.js轻量级跨平台图像编解码库 github:https://github.com/zhangyuanwei/node-images Features 功能特性 轻量级:无需安装任何图像处理库 ...
- Django---简单模板遍历渲染
简单路由: urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), path('list/', vi ...