Search code examples
c++boost-serialization

incorrect data from boost binary_iarchive read


I'm trying to read custom data from a binary file

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <fstream>

struct Data 
{
    int xs, ys;
    double ullat, ullon, lrlat, lrlon;
    double minval, maxval;

   // and some vector of floats
};

namespace boost { 
namespace serialization {

template <class Archive>
void
serialize (Archive& ar, Data& d, const unsigned int version)
{
    ar & d.xs & d.ys;
    ar & d.ullat & d.ullon & d.lrlat & d.lrlon;
    ar & d.minval & d.maxval;
}

} // namespace serialization
} // namespace boost

int main (void)
{
    std::ifstream fin ("test.bin", std::ios::in | std::ios::binary);

    // the binary file was not created by boost serialization library. No header information
    boost::archive::binary_iarchive arc (fin, boost::archive::no_header); 

    Data d;
    arc >> d;
}

After this, d contains junk values (huge -ve or +ve numbers).

If I use fstream::read to read the file following the layout of d I'm getting correct values. I'm unable to figure out what is going on here. As I commented in the code, the binary file was not created by boost serialization library. Hence using no_header flag.

I checked the binary file using hex viewer tool (ghex on linux) and fstream::read is returning correct values. What could be going wrong here?

I'm using gcc-8.3 and VS2017 with boost 1.70 and c++17


Solution

  • As I commented in the code, the binary file was not created by boost serialization library.

    In that case you won't be able to read the file using boost::archive::binary_iarchive unless your file happens to share the exact same binary format by chance.

    You will need to create a new implementation for the Loading Archive Concept as Boost calls it. In other words, a new archive type (for loading at least) that matchs your current format.

    Hence using no_header flag.

    This flag only skips the header that boost::archive::binary_oarchive writes for checking sizes/endianness etc., but it cannot read your data without knowing its format. That is why you have to write your own archive.