使用 sstream 中的提升binary_iarchive进行序列化和反序列化

serialize and deserialise using boost binary_iarchive from sstream

本文关键字:iarchive 序列化 反序列化 binary sstream 使用      更新时间:2023-10-16

最后,经过一番挣扎,我找到了一种序列化和反序列化std::map<int,map<int,structute values>的方法,并且能够打印值。

您能否澄清我对以下代码的疑问

  1. void serialize(archive & ar, const unsigned int version)用于序列化和反序列化的函数

  2. 我们可以在每个类和结构中为序列化和反序列化提供单独的函数吗?

  3. 同样的函数也可以用于创建xml吗,或者它是为xml提供单独的序列化和反序列化功能的巧妙方法

 #include <boost/archive/binary_oarchive.hpp>
 #include <boost/archive/binary_iarchive.hpp>
 #include <boost/serialization/binary_object.hpp>
 #include <boost/serialization/serialization.hpp>
 #include <iostream>
 #include <string>
 #include <iomanip>
 #include <sstream>
 #include <map>
 #include <boost/serialization/map.hpp>
   
struct values
{
    std::string name;
    std::string sex;
    values():name("dummy"),sex("dummy"){} ;
    template<class archive>
    void serialize(archive & ar,  const unsigned int version)
    {
      ar & name ;
      ar & sex ;
    }
};
class Myclass 
{
public:
    
  Myclass()
  {
    values val1;
    e_group.insert( std::make_pair(1,val1) ) ;
    e_group.insert( std::make_pair(2,val1) ) ;
    p_group.insert( std::make_pair(1,e_group) ) ;
    p_group.insert( std::make_pair(2,e_group) ) ;
  }
  template<class archive>
  void serialize(archive & ar,  const unsigned int version)
  {
    ar & e_group ;
    ar & p_group;
  }
  typedef   std::map<int,values> groups;
  typedef   std::map<int,groups> Pgroups;
  groups  e_group;
  Pgroups p_group;
};
int main() {
    char buf[256];
    Myclass obj;
    std::stringstream os(std::ios_base::binary| std::ios_base::out| std::ios_base::in);
    {
        boost::archive::binary_oarchive oa(os, boost::archive::no_header);
        oa << obj ;
      // oa << make_binary_object(&e_group, sizeof(e_group));
    }
   
   //print binary data
    std::string data = os.str();
    for (uint8_t ch : data) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(ch) << " ";
    }
    

    Myclass t2;
    {       
        memcpy(buf, os.str().data(), os.str().length());
        if(memcmp(buf, os.str().data(), os.str().length()) != 0)
          printf("memcpy errorn");
        std::stringstream is(std::string(buf, buf+os.str().length() ), std::ios_base::binary| std::ios_base::out| std::ios_base::in);
        boost::archive::binary_iarchive ia(is, boost::archive::no_header);
        ia >> t2;
    }
   for(auto &i:t2.p_group){
       std::cout<<"n"<<i.first<<"n";
        for(auto &j:i.second){
          std::cout<<"t"<<j.first<<"t"<<j.second.name<<"t"<<j.second.sex<<"n";
        }
   } 
   return 0;
}

更新:我更新了理查德的代码并添加了一个函数来取消二进制文件

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <map>
#include <boost/serialization/map.hpp>
#include <boost/serialization/split_member.hpp>

struct values
{
    std::string name;
    std::string sex;
    values():name("dummy"),sex("dummy"){} ;
    BOOST_SERIALIZATION_SPLIT_MEMBER();
    template<class Archive>
    void save(Archive & ar, const unsigned int version) const
    {
        // note, version is always the latest when saving
        ar & BOOST_SERIALIZATION_NVP(name);
        ar & BOOST_SERIALIZATION_NVP(sex);
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(name);
        ar & BOOST_SERIALIZATION_NVP(sex);
    }
};
class Myclass
{
public:
    Myclass()
    {
        values val1;
        e_group.insert( std::make_pair(1,val1) ) ;
        e_group.insert( std::make_pair(2,val1) ) ;
        p_group.insert( std::make_pair(1,e_group) ) ;
        p_group.insert( std::make_pair(2,e_group) ) ;
    }
    BOOST_SERIALIZATION_SPLIT_MEMBER();
    template<class Archive>
    void save(Archive & ar, const unsigned int version) const
    {
        // note, version is always the latest when saving
        ar & BOOST_SERIALIZATION_NVP(e_group);
        ar & BOOST_SERIALIZATION_NVP(p_group);
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(e_group);
        ar & BOOST_SERIALIZATION_NVP(p_group);
    }
    typedef   std::map<int,values> groups;
    typedef   std::map<int,groups> Pgroups;
    groups  e_group;
    Pgroups p_group;
};
template<class Archive, class Object>
std::string serialise_to_string(Object const& assetlist)
{
    auto os = std::ostringstream(std::ios::binary);
    Archive arch { os, boost::archive::no_header };
    arch << BOOST_SERIALIZATION_NVP(assetlist);
    return os.str();
};

std::ostream& dump(std::ostream& os, std::string const& s)
{
    const char *sep = "";
    for (uint8_t ch : s) {
        std::cout << sep << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(ch);
        sep = " ";
    }
    return os;
}
template<class Archive , class Object>
void deserialise_to_obj(std::string const &s1,Object &outObj)
{
    std::stringstream is( s1, std::ios_base::binary| std::ios_base::out| std::ios_base::in);
    Archive arch { is, boost::archive::no_header };
    arch >> BOOST_SERIALIZATION_NVP(outObj);
};

int main() {
    
    Myclass obj ;
    std::string  s1 = serialise_to_string<boost::archive::binary_oarchive>(obj);
    dump(std::cout, s1) << std::endl << std::endl;
    
    auto s2 = serialise_to_string<boost::archive::xml_oarchive>(obj);
   
   //Save xml to a file
    std::ofstream ofs("output.xml");
    ofs << s2 << std::endl << std::endl;
    
    //Deserialize the binary data to object
    Myclass outObj;
    deserialise_to_obj<boost::archive::binary_iarchive>(s1,outObj); 
    
    //Print the object 
    for(auto &i:outObj.p_group){
       std::cout<<"n"<<i.first<<"n";
        for(auto &j:i.second){
          std::cout<<"t"<<j.first<<"t"<<j.second.name<<"t"<<j.second.sex<<"n";
        }
    } 
}

使用 Coliru 编译的代码

如果我的方法错误,请建议我

我要感谢@sehe和@richard帮助我提升。

谢谢光辉

首先,不要这样做:

    memcpy(buf, os.str().data(), os.str().length());
    if(memcmp(buf, os.str().data(), os.str().length()) != 0)

这只是创建了一个字符串的 4 个独立副本。

现在的问题:

是否用于序列化和反序列化的

void 序列化(存档和 ar,const 无符号 int 版本(函数

是的

我们可以在每个类和结构中为序列化和反序列化提供单独的函数吗?

是的

同样的函数也可以用于创建xml吗,或者它是为xml提供单独的序列化和反序列化功能的巧妙方法

是的

您希望xml_oarchive和宏BOOST_SERIALIZATION_SPLIT_MEMBERBOOST_SERIALIZATION_NVP

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <map>
#include <boost/serialization/map.hpp>
#include <boost/serialization/split_member.hpp>

struct values
{
    std::string name;
    std::string sex;
    values():name("dummy"),sex("dummy"){} ;
    BOOST_SERIALIZATION_SPLIT_MEMBER();
    template<class Archive>
    void save(Archive & ar, const unsigned int version) const
    {
        // note, version is always the latest when saving
        ar & BOOST_SERIALIZATION_NVP(name);
        ar & BOOST_SERIALIZATION_NVP(sex);
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(name);
        ar & BOOST_SERIALIZATION_NVP(sex);
    }
};
class Myclass
{
public:
    Myclass()
    {
        values val1;
        e_group.insert( std::make_pair(1,val1) ) ;
        e_group.insert( std::make_pair(2,val1) ) ;
        p_group.insert( std::make_pair(1,e_group) ) ;
        p_group.insert( std::make_pair(2,e_group) ) ;
    }
    BOOST_SERIALIZATION_SPLIT_MEMBER();
    template<class Archive>
    void save(Archive & ar, const unsigned int version) const
    {
        // note, version is always the latest when saving
        ar & BOOST_SERIALIZATION_NVP(e_group);
        ar & BOOST_SERIALIZATION_NVP(p_group);
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(e_group);
        ar & BOOST_SERIALIZATION_NVP(p_group);
    }
    typedef   std::map<int,values> groups;
    typedef   std::map<int,groups> Pgroups;
    groups  e_group;
    Pgroups p_group;
};
template<class Archive, class Object>
std::string serialise_to_string(Object const& o)
{
    auto os = std::ostringstream(std::ios::binary);
    Archive arch { os, boost::archive::no_header };
    arch << BOOST_SERIALIZATION_NVP(o);
    return os.str();
};
std::ostream& dump(std::ostream& os, std::string const& s)
{
    const char *sep = "";
    for (uint8_t ch : s) {
        std::cout << sep << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(ch);
        sep = " ";
    }
    return os;
}
int main() {
    char buf[256];
    Myclass obj;
    auto s1 = serialise_to_string<boost::archive::binary_oarchive>(obj);
    dump(std::cout, s1) << std::endl << std::endl;
    auto s2 = serialise_to_string<boost::archive::xml_oarchive>(obj);
    std::cout<< s2 << std::endl << std::endl;
    return 0;
}

示例输出:

00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 64 75 6d 6d 79 05 00 00 00 00 00 00 00 64 75 6d 6d 79 02 00 00 00 05 00 00 00 00 00 00 00 64 75 6d 6d 79 05 00 00 00 00 00 00 00 64 75 6d 6d 79 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 05 00 00 00 00 00 00 00 64 75 6d 6d 79 05 00 00 00 00 00 00 00 64 75 6d 6d 79 02 00 00 00 05 00 00 00 00 00 00 00 64 75 6d 6d 79 05 00 00 00 00 00 00 00 64 75 6d 6d 79 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 05 00 00 00 00 00 00 00 64 75 6d 6d 79 05 00 00 00 00 00 00 00 64 75 6d 6d 79 02 00 00 00 05 00 00 00 00 00 00 00 64 75 6d 6d 79 05 00 00 00 00 00 00 00 64 75 6d 6d 79
<o class_id="0" tracking_level="0" version="0">
    <e_group class_id="1" tracking_level="0" version="0">
        <count>2</count>
        <item_version>0</item_version>
        <item class_id="2" tracking_level="0" version="0">
            <first>1</first>
            <second class_id="3" tracking_level="0" version="0">
                <name>dummy</name>
                <sex>dummy</sex>
            </second>
        </item>
        <item>
            <first>2</first>
            <second>
                <name>dummy</name>
                <sex>dummy</sex>
            </second>
        </item>
    </e_group>
    <p_group class_id="4" tracking_level="0" version="0">
        <count>2</count>
        <item_version>0</item_version>
        <item class_id="5" tracking_level="0" version="0">
            <first>1</first>
            <second>
                <count>2</count>
                <item_version>0</item_version>
                <item>
                    <first>1</first>
                    <second>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </second>
                </item>
                <item>
                    <first>2</first>
                    <second>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </second>
                </item>
            </second>
        </item>
        <item>
            <first>2</first>
            <second>
                <count>2</count>
                <item_version>0</item_version>
                <item>
                    <first>1</first>
                    <second>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </second>
                </item>
                <item>
                    <first>2</first>
                    <second>
                        <name>dummy</name>
                        <sex>dummy</sex>
                    </second>
                </item>
            </second>
        </item>
    </p_group>
</o>