【问题标题】:C++ : How to serialize/deserialize objects to binary archive format using Boost library? [duplicate]C++:如何使用 Boost 库将对象序列化/反序列化为二进制存档格式? [复制]
【发布时间】:2021-08-20 12:16:39
【问题描述】:

我已经成功地将我的 Employee 对象序列化为 文件格式 使用 Boost 库,我想使用 TCP/IP 通信协议通过套接字发送它,但我猜该协议不适用于文件。

我正在考虑将对象序列化和反序列化为二进制格式,但我不知道该怎么做,我在互联网上没有找到示例,请您帮帮我吗? p>

我将与您分享我的代码:

#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
 
using namespace std;
 
class Employee {
private:
   friend class boost::serialization::access;
   int id;
   string name;
   float salary;
   template<class Archive>
   void serialize(Archive &a, const unsigned version){
      a & id & name & salary;
   }
public:
   Employee(){}
   Employee(int i, string n, float s):id(i),name(n),salary(s)
   {}
};
 
int main()
{
   const string filename = "emp.dat";
   Employee e1(11,"Harry",4500.00f);
   Employee e2(22,"Ravi",8800.00f);
   Employee e3(33,"Tim",6800.00f);
   Employee e4(44,"Rajiv",3400.00f);
 
   // Serialize and persist the object
   {
      std::ofstream outfile(filename);
      boost::archive::text_oarchive archive(outfile);
      archive << e1 << e2 << e3 << e4;
   }
 
   // Deserialize and restore the object
   Employee restored_e1;
   Employee restored_e2;
   Employee restored_e3;
   Employee restored_e4;
 
   {
      std::ifstream infile(filename);
      boost::archive::text_iarchive archive(infile);
      archive >> restored_e1 >> restored_e2
         >> restored_e3 >> restored_e4;
   }
   return 0;
}

【问题讨论】:

  • I guess that this protocol does not work for files,为什么你猜我们不能通过 TCP 发送文件?您没有从网站下载任何文本吗?
  • @prehistoricpenguin 是的,它不适用于文件

标签: c++ serialization boost deserialization


【解决方案1】:

[总结]

a) 寻找一个接受套接字的 std::stream 兼容类。 (我认为 boost asio 有一个)。

b) 创建一个文件句柄并为其分配套接字句柄。

c) 警告:boost serialize Archive 概念并不适合您尝试做的事情。见下文。

[详情]

首先,您在这里问的内容与文本或二进制文件格式无关。原则上两者都适用于 tcp/ip。 text 以人类可读(文本)形式序列化您的数据,而二进制将简单地用二进制表示替换可读(文本)。这与数据的去向无关。

也就是说:您要做的是序列化到 tcp/ip 套接字而不是文件。这是可能的,尽管目前还不是很明显。 boost serialize 使用 Archive 作为 std::stream 的包装器。如果您有一个将数据写入 tcp/ip 套接字而不是文件的流,那将是您想要的。

[我的建议]

我将从 c) 开始:警告。 boost Archive 概念不容易通过套接字进行序列化。原因是通常每个文件只有一个存档。转换为套接字:您可以对每个连接准确地序列化一个存档。如果您需要序列化多个“存档”,则必须关闭连接并重新打开它。关闭和重新打开需要时间。

鉴于您还没有准备好 std::otcpstream,我自己的方法是将我的档案序列化到 std::o/istringstream 并通过 TCP/IP 发送整个字符串缓冲区。像这样:

   std::ostringstream out;
   {
      boost::text_archive outA(out);
      outA << do some serialization;
   }
   send_via_tcp(out.str());

注意:这里的括号很重要。 Archive 析构函数会向流中写入一个“结束”标签,因此除非调用析构函数,否则 out.str() 调用将产生一个不完整的字符串。

[直接序列化到 TCP/IP]

也就是说,您可以尝试直接序列化为 TCP/IP。问题是,没有序列化到套接字的 std::stream 类。例如,您期望有一个 std::otcpstream,但没有(在 std 中)。

a) 我认为 boost asio 有一个使用 TCP/IP 的流,所以你可以看看那里。

b) 第二个选项是打开一个套接字,然后为这个套接字创建一个文件句柄。 _dup() 函数接受一个套接字作为输入(我认为)。这样你就有了一个文件句柄(而不是一个套接字),并且可以为它创建一个 ofstream/ifstream。或者可能先创建 ofstream/ifstream 并使用 _dup 重新分配文件句柄。

我认为这将导致所有读/写调用转到 TCP/IP 堆栈而不是文件系统,因此理论上您应该能够写/读存档(完全是一个)。但是就像我上面说的,如果你的档案不是太大,我会简单地使用 stringstream 方法。

【讨论】:

    猜你喜欢
    • 2016-12-31
    • 1970-01-01
    • 2023-03-18
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多