如何在C++中使用boost库序列化自定义class ?| serialize and deserialize a class in cpp with boost
本文首发于个人博客https://kezunlin.me/post/6887a6ee/,欢迎阅读!
serialize and deserialize a class in cpp
Guide
how to serialize string
size + data
The easiest serialization method for strings or other blobs with variable size is to serialize first the size as you serialize integers, then just copy the content to the output stream.
When reading you first read the size, then allocate the string and then fill it by reading the correct number of bytes from the stream.
with ostream/istream
native way with ostream/istream for example class MyClass with height,width,name fields.
class MyClass {
public:
int height;
int width;
std::string name;
}
std::ostream& MyClass::serialize(std::ostream &out) const {
out << height;
out << ',' //number seperator
out << width;
out << ',' //number seperator
out << name.size(); //serialize size of string
out << ',' //number seperator
out << name; //serialize characters of string
return out;
}
std::istream& MyClass::deserialize(std::istream &in) {
if (in) {
int len=0;
char comma;
in >> height;
in >> comma; //read in the seperator
in >> width;
in >> comma; //read in the seperator
in >> len; //deserialize size of string
in >> comma; //read in the seperator
if (in && len) {
std::vector<char> tmp(len);
in.read(tmp.data() , len); //deserialize characters of string
name.assign(tmp.data(), len);
}
}
return in;
}
overload for operator<< and operator>>
std::ostream& operator<<(std::ostream& out, const MyClass &obj)
{
obj.serialize(out);
return out;
}
std::istream& operator>>(std::istream& in, MyClass &obj)
{
obj.deserialize(in);
return in;
}
with boost serialization
archive file format
- text: text_iarchive,text_oarchive
field - xml: xml_iarchive,xml_oarchive, with
BOOST_SERIALIZATION_NVP(field) - binary: binary_iarchive,binary_oarchive with
stringstreamorfstream.
text archive
change BOOST_SERIALIZATION_NVP(field) to field
xml archive
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
class Camera {
public:
int id;
std::string name;
double pos;
};
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive& archive, Camera& cam, const unsigned int version)
{
archive & BOOST_SERIALIZATION_NVP(cam.id);
archive & BOOST_SERIALIZATION_NVP(cam.name);
archive & BOOST_SERIALIZATION_NVP(cam.pos);
}
} // namespace serialization
} // namespace boost
std::ostream& operator<<(std::ostream& cout, const Camera& cam)
{
cout << cam.id << std::endl
<< cam.name << std::endl
<< cam.pos << std::endl;
return cout;
}
void save()
{
std::ofstream file("archive.xml");
boost::archive::xml_oarchive oa(file);
Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;
oa & BOOST_SERIALIZATION_NVP(cam);
}
void load()
{
std::ifstream file("archive.xml");
boost::archive::xml_iarchive ia(file);
Camera cam;
ia & BOOST_SERIALIZATION_NVP(cam);
std::cout << cam << std::endl;
}
void test_camera()
{
save();
load();
}
int main(int argc, char** argv)
{
test_camera();
}
binary archive
void save_load_with_binary_archive()
{
// binary archive with stringstream
std::ostringstream oss;
boost::archive::binary_oarchive oa(oss);
Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;
oa & (cam);
# get binary content
std::string str_data = oss.str();
std::cout << str_data << std::endl;
std::istringstream iss(str_data);
boost::archive::binary_iarchive ia(iss);
Camera new_cam;
ia & (new_cam);
std::cout << new_cam << std::endl;
}
binary archive with poco SocketStream
client.cpp
void test_client()
{
SocketAddress address("127.0.0.1", 9911);
StreamSocket socket(address);
SocketStream stream(socket);
//Poco::StreamCopier::copyStream(stream, std::cout);
boost::archive::binary_oarchive oa(stream);
Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;
oa & (cam);
}
server.cpp
void run()
{
Application& app = Application::instance();
app.logger().information("Request from " + this->socket().peerAddress().toString());
try
{
SocketStream stream(this->socket());
//Poco::StreamCopier::copyStream(stream, std::cout);
boost::archive::binary_iarchive ia(stream);
Camera new_cam;
ia & (new_cam);
std::cout << new_cam << std::endl;
}
catch (Poco::Exception& exc)
{
app.logger().log(exc);
}
}
notes on std::string
Even know you have seen that they do the same, or that .data() calls .c_str(), it is not correct to assume that this will be the case for other compilers. It is also possible that your compiler will change with a future release.
2 reasons to use std::string:
std::string can be used for both text and arbitrary binary data.
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
s1.c_str();
//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);
s2.data();
boost archive style
intrusive
private template<class Archive> void serialize(Archive& archive, const unsigned int version)friend class boost::serialization::access;
class Camera {
public:
int id;
std::string name;
double pos;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& archive, const unsigned int version)
{
archive & BOOST_SERIALIZATION_NVP(id);
archive & BOOST_SERIALIZATION_NVP(name);
archive & BOOST_SERIALIZATION_NVP(pos);
}
};
non-intrusive
class Camera {
public:
int id;
std::string name;
double pos;
};
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive& archive, Camera& cam, const unsigned int version)
{
archive & BOOST_SERIALIZATION_NVP(cam.id);
archive & BOOST_SERIALIZATION_NVP(cam.name);
archive & BOOST_SERIALIZATION_NVP(cam.pos);
}
} // namespace serialization
} // namespace boost
boost archive type
shared_ptr
boost::shared_ptr<T> instead of std::shared_prt<T>
and
#include <boost/serialization/shared_ptr.hpp>
Reference
- serializing-a-class-which-contains-a-stdstring
- is-it-possible-to-serialize-and-deserialize-a-class-in-c
- boost serialization
- boost serialization demo
- ibm boostserialization
- fast-data-image-transfer-server-client-using-boost-asio
History
- 20180128: created.
- 20180129: add intrusive,non-intrusive part.
Copyright
- Post author: kezunlin
- Post link: https://kezunlin.me/post/6887a6ee/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.
如何在C++中使用boost库序列化自定义class ?| serialize and deserialize a class in cpp with boost的更多相关文章
- [Java]LeetCode297. 二叉树的序列化与反序列化 | Serialize and Deserialize Binary Tree
Serialization is the process of converting a data structure or object into a sequence of bits so tha ...
- 如何在Webstorm中添加js库 (青瓷H5游戏引擎)
js等动态语言编码最大的缺点就是没有智能补全代码,webstorm做到了. qici_engine作为开发使用的库,如果能智能解析成提示再好不过了,经测试80%左右都有提示,已经很好了. 其他js库同 ...
- 在Linux中创建静态库.a和动态库.so
转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...
- 在Linux中创建静态库和动态库
我们通常把一些公用函数制作成函数库,供其它程序使用. 函数库分为静态库和动态库两种. 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库. 动态库在程序编译时并不会被连接到目标代码中 ...
- boost库的安装,使用,介绍,库分类
1)首先去官网下载boost源码安装包:http://www.boost.org/ 选择下载对应的boost源码包.本次下载使用的是 boost_1_60_0.tar.gz (2)解压文件:tar - ...
- 在Linux中创建静态库和动态库 (转)
我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为静态库和动态库两种.静态 库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不会被连接到目标代码中,而 ...
- VS2010 安装 Boost 库 1.54
Boost库被称为C++准标准库, 功能很是强大, 下面记录我在VS2010中安装使用Boost库的过程. 首先上官网http://www.boost.org/下载最新的Boost库, 我的版本是1_ ...
- windows上编译boost库
要用xx库,编译boost时就指定--with-xx.例如: # 下载并解压boost_1.58 # 进入boost_1.58目录 bjam.exe toolset=msvc-14.0 --build ...
- C++: Mac上安装Boost库并使用CLion开发
1.下载安装Boost库 官网下载最新版本1.65.0:http://www.boost.org/users/history/version_1_65_0.html 选择UNIX版本: 下载后解压cd ...
随机推荐
- 【python数据分析实战】电影票房数据分析(一)数据采集
目录 1.获取url 2.开始采集 3.存入mysql 本文是爬虫及可视化的练习项目,目标是爬取猫眼票房的全部数据并做可视化分析. 1.获取url 我们先打开猫眼票房http://piaofang.m ...
- CodeForces - 1214D D. Treasure Island
题目链接:https://vjudge.net/problem/2728294/origin 思路:可以抽象成管道,先试试能不能找到一个通道能通到终点, 如果可以则封锁这个通道,一个石头即可, 再试试 ...
- 使用 Hexo,Material Theme 以及 Github Pages 搭建个人博客
准备条件 Node.js npm Git GitHub账号 开始搭建 hexo init Blog cd Blog npm install hexo-deployer-git --save npm i ...
- 百万年薪python之路 -- MySQL数据库之 Navicat工具和pymysql模块
一. IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具,我们使用Navicat工具,这个工具本质上就是一个socket客户端,可视化的连接 ...
- 百万年薪python之路 -- 函数初始
1.函数 1.1 认识函数 定义一个事情或者是功能,等到需要的时候直接去用就好了.那么这里定义东西就是一个函数 函数:对代码块和功能的封装和定义 函数的好处: 减少代码的重复性 代码可读性高 将功能进 ...
- 基于Groovy搭建Ngrinder脚本调试环境
介绍 最近公司搭建了一套压力测试平台,引用的是开源的项目 Ngrinder,做了二次开发,在脚本管理方面,去掉官方的SVN,引用的是Git,其他就是做了熔断处理等. 对技术一向充满热情的我,必须先来拥 ...
- @EnableTransactionalManager 发生了什么
@EnableTransactionalManager 利用TransactionManagementConfigurationSelector 给容器中注入bean,导入2个组件: AutoProx ...
- python wraps的作用
1.__name__用来显示函数的名称,__doc__用来显示文档字符串也就是("""文档字符串""")这里面的内容 2.首先我们来看不加@ ...
- redis操作总结
一.redis 终端操作命令: 1.redis-server.exe redis.windows.conf #指定配置文件启动 2.redis-cli #链接redis数据库 3.select 1 # ...
- ORM之多表操作
一.创建模型 from django.db import models # Create your models here. class Book(models.Model): nid = model ...