1

I am very new to Cereal, and I have a (possible simple) question:

Is there a way to deserialize multiple objects when I don't know the number of objects inside the (XML) archive?

I tried something like:

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

Let's say I have 3 objects in the XML file and the XML that I receive hasn't the containing object number. So, in my code, the first 3 iteration are OK, but the 4th generates "Unhandled exception at 0x0035395E in CerealTest.exe: 0xC0000005: Access violation reading location 0x00000018."

Do you have any suggestion?

Metallaru
  • 11
  • 1
  • 2
  • 1
    Welcome to StackOverflow. If possible, you should compile this with debugging enabled so that you can post an exception with the line numbers. And explain what you've tried (see http://stackoverflow.com/help/how-to-ask) – Martin Serrano Apr 04 '14 at 13:25

1 Answers1

4

Let me ask you a question before trying to answer your question: if you are serializing an unknown number of items, why not place those items in some container designed to hold a variable number of items? You could use an std::vector to store your ObjectIn and easily handle any number of them. Your code would look something like:

std::vector<MyObjects> vec;
{
  cereal::XMLInputArchive ar("filename");
  ar( vec );
} // get in the habit of using cereal archives in an RAII fashion

The above works with any number of objects serialized, assuming that cereal generated the XML to begin with. You can even add or remove elements from the vector in the XML code and it will work properly.


If you are insistent on reading some unknown number of objects and not placing them in a container designed to hold a variable number of elements, you can it something like this (but be warned this is not a good idea - you should really try to change your serialization strategy and not do this):

{
  cereal::XMLInputArchive ar("filename");
  try
  {
    while( true )
    {
      ObjectIn ob;
      ar( ob );
      objectList.push_back(oIn);
    }
  catch( ... )
  { }
}

Again let me stress that this is fundamentally a problem with your serialization strategy and you should be serializing a container instead of items a-la-carte if you don't know how many there will be. The above code can't handle reading in anything else, it just tries to blindly read things in until it encounters an exception. If your objects followed some naming pattern, you could use name-value-pairs (cereal::make_nvp) to retrieve them by name.

Azoth
  • 1,652
  • 16
  • 24
  • Hello and thank you for answering. Trying to serialize a std::vector or std::list generates the following error: "Error 10 error C2338: Trying to serialize an unserializable type with an output archive. ..\src\include\cereal\cereal.hpp 453" – Metallaru Apr 08 '14 at 11:58
  • Also, the try / catch didn't work, it just raises a lot of "First-chance exception at ... Access violation reading location ..." – Metallaru Apr 08 '14 at 12:09
  • 1
    If you serialize list or vector you need to include the appropriate header in the types folder. – Azoth Apr 08 '14 at 22:46
  • Yes, now it works. But, as you say, I need also to use cereal to create the XML file, and this is not the case here. My application needs to consume XML made by other applications, so I think cereal is not the right tool for me. Thank you very much for answering. – Metallaru Apr 09 '14 at 08:58
  • @Azoth Why the good() does not return false in this case? I mean we reached the end of the file and we fail to read. Why the good function still returns true? – Minee Mar 01 '19 at 16:44