[boost::serialization] Newbie question on de-serializing a collection without reading into an STL

Apologies for the basic nature of this question . but I've scoured the documentation for the Boost Serialization library without any hint of how to solve this. I want to use the Boost Serialization library to allow the saving and loading of a collection of database rows. This will use XML as the file format. All of the examples in the documentation assume that there is a "root" object saved, and in the case of a collection on objects, just save and load the collection itself: void save_mib(const vector<Row>& mib, const string& filename) { ofstream ofs(filename.c_str()); boost::archive::xml_oarchive oa(ofs); oa << BOOST_SERIALIZATION_NVP(mib); } void load_mib(vector<Row>& mib, const string& filename) { ifstream ifs(filename.c_str()); boost::archive::xml_iarchive ia(ifs); ia >> BOOST_SERIALIZATION_NVP(mib); } However, this will be a LARGE collection of rows, and I don't want to read them all in at once. Instead, I want to read them in, one at a time and process piecemeal. However, I can't work out from the documentation how to test that there is another row left to read . So, I can successfully output a list of rows: void save_mib(const vector<Row>& mib, const string& filename) { ofstream ofs(filename.c_str()); boost::archive::xml_oarchive oa(ofs); const vector<Row>::const_iterator mibEnd(mib.end()); for (vector<Row>::const_iterator i(mib.begin()); i != mibEnd; ++i) { const Row& row(*i); oa << BOOST_SERIALIZATION_NVP(row); } } I have not been able to deduce how to read these back in again without relying on there being a "stream error" exception thrown . void load_mib(vector<Row>& mib, const string& filename) { ifstream ifs(filename.c_str()); boost::archive::xml_iarchive ia(ifs); Row row; try { while (1) { ia >> BOOST_SERIALIZATION_NVP(row); mib.push_back(row); } } catch (boost::archive::archive_exception& ae) { cout << "caught archive_exception '" << ae.what() << "'\n"; } catch (exception& e) { cout << "caught exception '" << e.what() << "'\n"; } catch (...) { cout << "caught unknown exception\n"; } } Is that the best way to do it? Surely there is a better, exception-free, method? Also, can anyone please suggest a way of doing this using ostream_iterators and istream_iterators? Thank you for reading this far! Graham.

How about the following ( using the serialization of std::vector as a model) void save_mib(const vector<Row>& mib, const string& filename) { ofstream ofs(filename.c_str()); boost::archive::xml_oarchive oa(ofs); oa << mib.size(); // might need a "const" cast here const vector<Row>::const_iterator mibEnd(mib.end()); for (vector<Row>::const_iterator i(mib.begin()); i != mibEnd; ++i) { const Row& row(*i); oa << BOOST_SERIALIZATION_NVP(row); } } void load_mib(vector<Row>& mib, const string& filename) { ifstream ifs(filename.c_str()); boost::archive::xml_iarchive ia(ifs); unsigned int count; ia >> count; while(count-- > 0) { ia >> BOOST_SERIALIZATION_NVP(row); mib.push_back(row); } } } But this is the same as using a std::vector. So you might want something that doesn't require an itermediate data structure: // since we might use a temporary object upon saving and are often going to "throw away" the temporary object upon loading // make sure that it doesn't optimize saving/loading of pointed to objects. BOOST_SERIALIZATION_TRACKING(Row, no_tracking); typedef ... row_iterator; void save_mib(const unsigned int count, const row_iterator it, const string& filename) { ofstream ofs(filename.c_str()); boost::archive::xml_oarchive oa(ofs); oa << count; const vector<Row>::const_iterator mibEnd(mib.end()); for (vector<Row>::const_iterator i(mib.begin()); i != mibEnd; ++i) for(unsigned int i = count; i-- > 0;){ oa << *it; } } typedef ... function_object; void load_mib(function_object & fo, const string& filename) { ifstream ifs(filename.c_str()); boost::archive::xml_iarchive ia(ifs); unsigned int count; ia >> count; while(count-- > 0) { Row row; ia >> BOOST_SERIALIZATION_NVP(row); fo(row); } } } Good luck with this. Robert Ramey
participants (2)
-
Graham Hudspith
-
Robert Ramey