如何在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
stringstream
orfstream
.
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.
最新文章
- HTML5 中的新属性autocomplete=";off";失效的解决方法(兼容firefox,IE,360)
- [Android]listview recycleview的复用问题
- Android Studio Exception汇总
- visual studio 2012如何彻底删除TFS上的团队项目
- BZOJ3831 : [Poi2014]Little Bird
- iOS-OC根据时间戳获取距离现在的状态(刚刚,分钟前,今天,昨天)
- java后台SSH框架之Hibernate心得一
- [转载]JS对URL的编码
- php生成缩略图
- iOS定位功能
- android handler工作原理
- Linux 内核综述
- Iview的开发之路
- 看完此文还不懂NB-IoT,你就过来掐死我吧...【转】
- Spring 注入集合
- Python_迭代器、生成器、列表推导式,生成器表达式
- 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)
- [dpdk][sysfs][pci] 在dpdk程序中操纵PCI设备
- php正则的使用
- s11.1 lsof:查看进程打开的文件
热门文章
- Js极客之路 - 简化操作
- 线性回归 python 代码实现
- 用Wireshark抓包分析请求
- vue+webpack+element-ui项目打包优化速度与app.js、vendor.js打包后文件过大
- django-模板之自定义模板路径(一)
- hash算法的应用
- net core WebApi——使用xUnits来实现单元测试
- Python编程 Notepad++和Pycharm设置
- 「Usaco2008 Jan」人工湖O(∩_∩)O 纯属的模拟+栈
- P4568 [JLOI2011]飞行路线 分层图