如何在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 ...
随机推荐
- 如何在 GitHub 的项目中创建一个分支呢?
如何在 GitHub 的项目中创建一个分支呢? 其实很简单啦,直接点击 Branch,然后在弹出的文本框中添加自己的 Branch Name 然后点击蓝色的Create branch就可以了,这样一来 ...
- Spring Cloud Alibaba(三)Sentinel之熔断降级
本项目演示如何使用 Sentinel 完成 Spring Cloud 应用的熔断降级调用. Sentinel 是阿里巴巴开源的分布式系统的流量防卫组件,Sentinel 把流量作为切入点,从流量控制, ...
- Spring Data - Spring Data JPA 提供的各种Repository接口
Spring Data Jpa 最近博主越来越懒了,深知这样不行.还是决定努力奋斗,如此一来,就有了一下一波复习 演示代码都基于Spring Boot + Spring Data JPA 传送门: 博 ...
- Charles抓包工具的使用(一)
前提:charles的说明 Charles其实是一款代理服务器,通过过将自己设置成系统(电脑或者浏览器)的网络访问代理服务器,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在W ...
- Linux进程和线程
一.进程产生的方式 1.描述进程的ID号通常叫做PID,即进程ID,PID的变量类型为pid_t. 2.getpid(void)返回当前进程的ID号,getppid(void)返回当前进程的父进程的I ...
- Type of the default value for 'songs' prop must be a function
eslint常会出现这样的错误提示,控制台打印:Type of the default value for 'songs' prop must be a function 解决办法有两种如下: 1:写 ...
- 设计模式C++描述----12.享元(Flyweight)模式
一. 概述 在面向对象系统的设计何实现中,创建对象是最为常见的操作. 这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销.特别是对于大量轻量级(细粒度)的对象,比如在文档编辑 ...
- .NET webAPI中集成swagger
最近做的项目使用winform三层+webapi,对于webAPI路由文档管理一直觉得单独做一些管理比较麻烦,并且测试的时候项目内的代码测试运行起来也比较麻烦,所以在网上开始检索相关办法,发现热度比较 ...
- Linux系统运行级别和关机重启命令介绍
Linux系统运行级别介绍 Linux系统有七种运行级别(Run Level),各个运行级别下,系统有不同的状态,各个级别的意义描述如下. 0:关键级别1:单用户运行级别,运行rc.sysinit和r ...
- data-*设置自定义属性注意事项一
本人才疏学浅,偶遇一个data自定义属性应当注意的小问题,随笔记下. 1.看下面代码:首先在a标签设置自定义两个属性 <a class="btn" href="ja ...