Я очень новичок в Cereal, и у меня есть (возможно простой) вопрос:
Есть ли способ десериализации нескольких объектов, когда я не знаю количество объектов в (XML) архиве?
Я попробовал что-то вроде:
std::ifstream is("c:\\data.xml");
cereal::XMLInputArchive archive(is);
while (is.good() && !is.eof())
{
try{
ObjectIn oIn;
archive(oIn);
objectList.push_back(oIn);
}
catch (exception e){
}
}
Допустим, у меня есть 3 объекта в файле XML, а в полученном XML нет номера объекта. Итак, в моем коде первые 3 итерации в порядке, но 4-й генерирует
«Необработанное исключение в 0x0035395E в CerealTest.exe: 0xC0000005: расположение чтения нарушения доступа 0x00000018.»
Есть ли у вас предложения?
Позвольте мне задать вам вопрос, прежде чем пытаться ответить на ваш вопрос: если вы сериализуете неизвестное количество элементов, почему бы не поместить эти элементы в какой-либо контейнер, предназначенный для хранения переменного количества элементов? Вы могли бы использовать std::vector
хранить ваши ObjectIn
и легко справиться с любым количеством из них. Ваш код будет выглядеть примерно так:
std::vector<MyObjects> vec;
{
cereal::XMLInputArchive ar("filename");
ar( vec );
} // get in the habit of using cereal archives in an RAII fashion
Вышеописанное работает с любым количеством сериализованных объектов, при условии, что зерновые сгенерировали XML для начала. Вы даже можете добавлять или удалять элементы из вектора в коде XML, и это будет работать правильно.
Если вы настаиваете на том, чтобы прочитать какое-то неизвестное количество объектов и не помещать их в контейнер, предназначенный для хранения переменного количества элементов, вы можете сделать это примерно так (но учтите, что это не очень хорошая идея — вам действительно следует попытаться изменить твоя стратегия сериализации и не делай этого)
{
cereal::XMLInputArchive ar("filename");
try
{
while( true )
{
ObjectIn ob;
ar( ob );
objectList.push_back(oIn);
}
catch( ... )
{ }
}
Еще раз позвольте мне подчеркнуть, что это принципиально проблема с вашей стратегией сериализации, и вам следует сериализовать контейнер вместо элементов а-ля-карт, если вы не знаете, сколько их будет. Приведенный выше код не может обрабатывать чтение во всем остальном, он просто пытается вслепую читать, пока не встретит исключение. Если ваши объекты следуют некоторому шаблону именования, вы можете использовать пары имя-значение (cereal::make_nvp
) чтобы получить их по имени.
Других решений пока нет …