【问题标题】:boost serialization multiple objects提升序列化多个对象
【发布时间】:2011-08-18 16:44:47
【问题描述】:

this onethis one 略有相关的问题。

基本上,我想在对象到来时对其进行序列化,就像日志文件一样,只是我想稍后再对它们进行反序列化。这意味着我最初没有所有对象。

从以前的答案看来,如果一个人保持打开同一个档案,人们可​​以继续向档案中添加越来越多的对象。

但我将如何提取它们?我是否需要提前查看是否在每次提取之前达到了 eof ?我是否应该在保存例程中放置一个换行符,以便以后可以逐行读取输入(这可能仅适用于二进制存档(可能是文本),因为 xml 使用换行符,如果二进制文件可能使用偶尔换行)?如果到达文件末尾,也许 >> 操作会引发异常,我可以将它包装在一个无限循环中,并在其周围使用 try catch?

如果我想为不同种类的对象这样做,我该怎么做?也许有一个所有对象的枚举并在之前序列化枚举,并且在反序列化时有一个基于枚举的开关?

谢谢

【问题讨论】:

标签: c++ serialization boost


【解决方案1】:

您所说的实际上并不是序列化的重点。序列化设计为在写入和读取的顺序由编译时确定时工作。甚至版本控制也是编译时;您要么序列化一个值,要么不基于运行时版本。订单被保留。

现在,您可以在输出中添加一些标记,即某种映射到类类型的整数值。也就是说,在将类写入流之前,您写入一个表示该类是什么的整数。然后你稍后阅读它并根据它决定下一个序列化的类型。

但是您会遇到的问题是,您最终会用完内容。而且连载档案也没有办法说“仅此而已”。它们应该是在编译时定义的,所以在输入结束之后读取被认为是用户错误。所以处理任意数量的序列化数据并不容易。

同样,您可以在输出中写入一个特殊标记,即“这就是结束”。

【讨论】:

    【解决方案2】:

    这就是我最后所做的。由于 Nicol 是对的,而且这确实有点不符合预期,所以第一个必须确保禁用指针跟踪。否则会得到虚假的共享对象。因此,首先,大量的

    BOOST_CLASS_TRACKING(yourDerivedClass,boost::serialization::track_never)
    

    我还决定只记录派生自同一基础对象的对象(您可以为此创建一个空的虚拟基础)。一旦完成,确保它被视为抽象很重要(我确保有虚拟析构函数,并且仍然添加了

    BOOST_SERIALIZATION_ASSUME_ABSTRACT(yourBaseClass)
    

    在创建存档后将所有派生类注册到存档(写入和读取)

    arMsgs.template register_type<yourDerivedClass>();
    

    只注册final非抽象类(如果A派生自B派生自C,则不注册B)。至少任何注册的类都需要禁用跟踪。

    最后将它们添加到存档中。

    为了重新加载它们,而不是使用需要检查的特殊标记作为文件结尾,我选择了

    try 
    {
        for(;;)
        {
            yourBaseClass obj;
            arObjs >> boost::serialization::make_nvp("Obj",obj);
            //your logic
        }
    }
    catch(boost::archive::archive_exception const& e) { }
    

    这可能有点太多了,所以可能需要一些额外的检查,但这对我有用。优点是正确关闭并不那么重要,例如如果您的应用在中途崩溃,您仍然可以处理到最后一条可读消息。

    【讨论】:

      【解决方案3】:

      我正在学习 boost,我认为您可以将 boost 序列化用作日志文件,并使用您的逻辑继续添加值。我遇到了同样的问题,如果我没记错的话,你的代码是这样的:

      #include <iostream>
      #include <fstream>
      #include <boost/archive/text_iarchive.hpp>
      #include <boost/archive/text_oarchive.hpp>
      
      int main()  {
          int two=2;
      
          for(int i=0;i<10;i++)   {
      
              std::ofstream ofs("table.txt");
              boost::archive::text_oarchive om(ofs);
              om << two;
              two = two+30;
              std::cout<<"\n"<<two;
          }
      
          return 0;
      }
      

      在这里,当您关闭大括号(循环的大括号)时,序列化文件将关闭。而且你可能会看到 table.txt 中只有一个值,如果你想存储多个值,你的代码应该是这样的:

      #include <iostream>
      #include <fstream>
      #include <boost/archive/text_iarchive.hpp>
      #include <boost/archive/text_oarchive.hpp>
      
      int main()  {
          int two=2;
      
          {
              std::ofstream ofs("table.txt");
              boost::archive::text_oarchive om(ofs);
              for(int i=0;i<10;i++)   {
      
                  om << two;
                  two = two+30;
                  std::cout<<"\n"<<two;
              }
          }
      
          return 0;
      }
      

      在这里您可以看到,包围 boost::serialization::text_oarchive 的大括号仅在我完成逻辑结果的序列化后才会关闭。

      【讨论】:

      • 对。或者只是使文件流附加在循环内。 std::ofstream ofs("table.txt",std::ios::app);
      猜你喜欢
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 2013-05-01
      • 1970-01-01
      • 2011-06-25
      相关资源
      最近更新 更多