повысить сериализацию нескольких объектов - PullRequest
4 голосов
/ 18 августа 2011

Слегка связанный вопрос с этим и этим .

По сути, я хотел бы сериализовать объекты по мере их поступления, очень похоже на файл журнала, за исключением того, что я хочу снять их сериализацию позже. Это означает, что у меня не все объекты изначально.

Судя по предыдущим ответам, если держать один и тот же архив открытым, можно добавлять все больше и больше объектов в архив.

Но как бы мне их извлечь? Нужно ли смотреть в будущее и видеть, достигается ли eof перед каждым извлечением? Должен ли я поместить разрыв строки в подпрограмму сохранения, чтобы впоследствии я мог читать ввод за строкой (это, вероятно, будет работать только с двоичными архивами (и, возможно, с текстом), поскольку xml использует разрывы строк, и, возможно, даже там, если двоичный файл может использовать разрыв строки иногда)? Может быть, операция >> выдает исключение, если достигнут конец файла, и я могу обернуть его в бесконечный цикл с попыткой его обойти?

И как бы я поступил, если бы хотел сделать это для разных типов объектов? Может быть, иметь перечисление для всех объектов и сериализовать перечисление непосредственно перед, а при десериализации иметь переключатель на основе перечисления?

Спасибо

Ответы [ 3 ]

2 голосов
/ 23 августа 2011

Вот что я сделал в конце.Поскольку Ник прав, и это действительно нецелевое использование, сначала нужно отключить отслеживание указателя.В противном случае можно получить поддельные общие объекты.Следовательно, для начала, загрузки

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) { }

Это может отловить слишком много, поэтому могут потребоваться дополнительные проверки, но это работает для меня. Преимущество заключается в том, что правильное завершение не так важно, например, если ваше приложение дает сбой в середине, вы все равно можете выполнить допоследнее читаемое сообщение.

2 голосов
/ 18 августа 2011

То, о чем вы говорите, на самом деле не является целью сериализации.Сериализация предназначена для работы, когда порядок записи и чтения определяется во время компиляции.Даже управление версиями происходит во время компиляции;вы либо сериализуете значение, либо не основываетесь на runtime-версии.Порядок сохраняется.

Теперь вы могли бы добавить несколько выводов к выходам, какое-то целочисленное значение, которое отображается на типы классов.То есть перед записью класса в поток вы пишете целое число, представляющее, что это за класс.Затем вы читаете его позже и решаете, какой тип сериализовать дальше, основываясь на этом.

Но проблема, с которой вы столкнетесь, заключается в том, что, в конце концов, у вас кончится контент.И в архивах сериализации на самом деле нет способа сказать «вот и все».Ожидается, что они будут определены во время компиляции, поэтому чтение после окончания ввода считается ошибкой пользователя.Таким образом, обработка произвольных объемов сериализованных данных не так легко поддерживается.

Опять же, вы можете записать специальный вывод в вывод, что-то вроде «это конец».

0 голосов
/ 07 февраля 2014

Я изучаю 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, закрываются только после завершения сериализации результата моей логики.

...