增强多对象序列化

boost serialization multiple objects

本文关键字:序列化 多对象 增强      更新时间:2023-10-16

这个和这个有点关系

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

从之前的回答来看,如果一个人保持相同的存档打开,他可以继续向存档添加越来越多的对象。

但是我如何提取它们呢?我是否需要在每次拔牙前提前查看是否达到eof ?我是否应该在保存例程中放置换行符,以便以后可以逐行读取输入(这可能只适用于二进制文件(也可能适用于文本),因为xml使用换行符,如果二进制文件偶尔使用换行符,可能就不存在了)?也许>>操作抛出一个异常,如果到达文件结束,我可以包装它在一个无限循环与周围的尝试捕获?

如果我想对不同类型的对象这样做,我该怎么做呢?也许对所有对象都有一个枚举,并在之前序列化枚举,然后在反序列化时基于枚举进行切换?

谢谢

您所谈论的并不是序列化的真正意义。序列化被设计为在编译时确定写入和读取的顺序时工作。甚至版本控制也是编译时的;您可以根据运行时版本序列化值,也可以不序列化值。顺序保留。

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

但你将遇到的问题是,最终,你将耗尽内容。而连载档案并没有真正的方式说"这就是全部。"它们应该是编译时定义的,因此读取超过输入结束部分被认为是用户错误。因此,不容易支持处理任意数量的序列化数据。

同样,您可以在输出中写入一个特殊的标记,表示"这是结束"。

下面是我最后做的。既然Nicol是对的,而且这确实有点非预期的用途,那么首先必须确保禁用指针跟踪。否则就会得到虚假的共享对象。因此,从

的加载开始
BOOST_CLASS_TRACKING(yourDerivedClass,boost::serialization::track_never)

我还决定只记录从相同基对象派生的对象(您可以为此目的创建一个空的虚拟基)。一旦这样做了,重要的是要确保它是抽象的(我确保有虚析构函数,并且仍然添加了

)。
BOOST_SERIALIZATION_ASSUME_ABSTRACT(yourBaseClass)

在创建归档文件后注册所有派生类(包括写和读)

arMsgs.template register_type<yourDerivedClass>();

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

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

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

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

这可能会捕获太多,所以可能需要一些额外的检查,但这对我来说是有效的。这样做的好处是适当的关闭并不是那么重要,例如,如果你的应用程序在中途崩溃,你仍然可以处理直到最后一个可读的消息。

我正在学习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的大括号只有在我完成了逻辑结果的序列化后才会关闭。