zoukankan      html  css  js  c++  java
  • 如何在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 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("abb", 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

  • 相关阅读:
    OpenCv 学习安装(一)
    mysql 5.7.22安装
    sql游标
    (转)C# 获取当前路径的7中方法
    IIS 配置好了,为什么网站打开一片空白?
    (转)C#文件操作
    关于电脑开机不出现桌面即不启动explorer.exe桌面程序--------正解
    C#中 非静态字段、方法或属性“XXXX”要求对象引用-----解决方案
    关于svn获取获取文件时 Unable to connect to a repository at URL"https://..."执行上下文错误:参数错误
    获取汉字全拼、首字母缩写
  • 原文地址:https://www.cnblogs.com/kezunlin/p/11840592.html
Copyright © 2011-2022 走看看