本文首发于个人博客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 stringstream or fstream.

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

History

  • 20180128: created.
  • 20180129: add intrusive,non-intrusive part.

Copyright

如何在C++中使用boost库序列化自定义class ?| serialize and deserialize a class in cpp with boost的更多相关文章

  1. [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 ...

  2. 如何在Webstorm中添加js库 (青瓷H5游戏引擎)

    js等动态语言编码最大的缺点就是没有智能补全代码,webstorm做到了. qici_engine作为开发使用的库,如果能智能解析成提示再好不过了,经测试80%左右都有提示,已经很好了. 其他js库同 ...

  3. 在Linux中创建静态库.a和动态库.so

    转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...

  4. 在Linux中创建静态库和动态库

    我们通常把一些公用函数制作成函数库,供其它程序使用. 函数库分为静态库和动态库两种. 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库. 动态库在程序编译时并不会被连接到目标代码中 ...

  5. boost库的安装,使用,介绍,库分类

    1)首先去官网下载boost源码安装包:http://www.boost.org/ 选择下载对应的boost源码包.本次下载使用的是 boost_1_60_0.tar.gz (2)解压文件:tar - ...

  6. 在Linux中创建静态库和动态库 (转)

    我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为静态库和动态库两种.静态 库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不会被连接到目标代码中,而 ...

  7. VS2010 安装 Boost 库 1.54

    Boost库被称为C++准标准库, 功能很是强大, 下面记录我在VS2010中安装使用Boost库的过程. 首先上官网http://www.boost.org/下载最新的Boost库, 我的版本是1_ ...

  8. windows上编译boost库

    要用xx库,编译boost时就指定--with-xx.例如: # 下载并解压boost_1.58 # 进入boost_1.58目录 bjam.exe toolset=msvc-14.0 --build ...

  9. C++: Mac上安装Boost库并使用CLion开发

    1.下载安装Boost库 官网下载最新版本1.65.0:http://www.boost.org/users/history/version_1_65_0.html 选择UNIX版本: 下载后解压cd ...

随机推荐

  1. redis之Scan

    scan 相比keys 具备有以下特点:1.复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程;2.提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是一个 hin ...

  2. 基于docker的mysql8的主从复制

    基于docker的mysql8的主从复制 创建mysql的docker镜像 构建docker镜像,其中数据卷配置内容在下面,结构目录如下 version: '3.7' services: db: # ...

  3. SpringCloud学习--微服务架构

    目录 微服务架构快速指南 SOA Dubbo Spring Cloud Dubbo与SpringCloud对比 微服务(Microservice)架构快速指南 什么是软件架构? 软件架构是一个包含各种 ...

  4. CMMS系统中工单派案&调度

    系统为客户经理提供一个有效的调度控制台,由客户经理负责将需要外派现场处理的工单进行统一的分配调度,系统显示每个技术人员的时间表,根据专业技能.可用性.距离或其他资格标准筛选技术服务人员,并向调度人员提 ...

  5. 用Python新建用户并产生随机密码

    说明:本次代码是在Linux下执行的,windows也可以用,把添加用户密码的命令改成windows的就ok了 用Python新建用户并产生随机密码 import passwd_name as pn ...

  6. python 读取文件夹中的文件内容

    看thinking in java的时候发现有个题的答案不确定结果, 于是下载答案看下,结果是 这个样子的,这样要怎么才能找到相对应的答案?于是我就着手写了一个快速遍历的脚本(我这里只是单纯的找了出来 ...

  7. Redis(十)集群:Redis Cluster

    一.数据分布 1.数据分布理论 2.Redis数据分区 Redis Cluser采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=CRC16(key)&16 ...

  8. 基本的sql 语句

    1,登陆数据库:mysql -u root -p2,退出数据库:exit quit ctr+d3,创建数据库:create database 数据库名 charset=utf84,使用数据库:use ...

  9. vue-socket.io 及 egg-socket.io 的简单使用

    egg-socket.io 的使用 官方文档看这里 egg-socket.io 接下来的内容其实与文档里差不多,介意的童鞋略过就好,目前只是简单的引入,下周往后会写复杂些的逻辑,在后面的文章会介绍. ...

  10. [2018-08-03] python开发个人资源共享网--第一天

    项目需求-环境搭建 python版本:python 3.6.2 开发工具:PyCharm 数据库:MySql5.7.24 数据库管理工具:Navicat 环境搭建完毕 ---------------- ...