Practical examples of using Boost serialization

Listing1: Serialization of STL containers: a std::vector example using text archives Your intuition may tell you to iterate through the STL container in order to serialize it, but it's actually a lot simpler. First of all, be sure to include the necessary vector.hpp include file: [code language="cpp"] #include <boost/serialization/vector.hpp>; [/code] And then simply serialize the std::vector data member(s): [code language="cpp"] template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & filenames; } [/code] [code language="cpp"] #include <iostream> #include <vector>; #include <fstream>; #include <boost/serialization/vector.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> class Info { private: // Allow serialization to access non-public data members. friend class boost::serialization::access; // Serialize the std::vector member of Info template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & filenames; } std::vector<std::string> filenames; public: void AddFilename( const std::string& filename ); void Print() const; }; void Info::Print() const { std::copy(filenames.begin(), filenames.end(), std::ostream_iterator<std::string>(std::cout, "\n")); } void Info::AddFilename( const std::string& filename ) { filenames.push_back( filename ); } int main(int argc, char** argv) { Info info; info.AddFilename( "ThisFile.txt" ); info.AddFilename( "ThatFile.txt" ); info.AddFilename( "OtherFile.txt" ); // Save filename data contained in Info object { // Create an output archive std::ofstream ofs( "store.dat" ); boost::archive::text_oarchive ar(ofs); // Save the data ar & info; } // Restore from saved data and print to verify contents Info restored_info; { // Create and input archive std::ifstream ifs( "store.dat" ); boost::archive::text_iarchive ar(ifs); // Load the data ar & restored_info; } restored_info.Print(); return 0; } [/code] Giving you the following output from the restored Info data: [code language="cpp"] ThisFile.txt ThatFile.txt OtherFile.txt [/code] Listing 2: Explicitly defining save and load functions You may need to explicitly define the save and load functions whenever there is asymmetry, such as when versioning is involved. In other words when you don't want to use the same serialize method to store and restore objects. The is easily achieved by use of the BOOST_SERIALIZATION_SPLIT_MEMBER() macro, along with splitting the serialize method into separate save and load methods. Full code listing as follows, which serializes the same Info object: [code language="cpp"] #include <iostream> #include <vector> #include <fstream> #include <boost/serialization/vector.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp>; #include <boost/serialization/split_member.hpp> class Info { private: // Allow serialization to access non-public data members. friend class boost::serialization::access; template<class Archive> void save(Archive & ar, const unsigned int version) const { ar & filenames; } template<class Archive> void load(Archive & ar, const unsigned int version) { ar & filenames; } BOOST_SERIALIZATION_SPLIT_MEMBER() std::vector<std::string> filenames; public: void AddFilename( const std::string& filename ); void Print() const; }; void Info::Print() const { std::copy(filenames.begin(), filenames.end(), std::ostream_iterator&lt;std::string>(std::cout, "\n")); } void Info::AddFilename( const std::string& filename ) { filenames.push_back( filename ); } int main(int argc, char** argv) { Info info; info.AddFilename( "ThisFile.txt" ); info.AddFilename( "ThatFile.txt" ); info.AddFilename( "OtherFile.txt" ); // Save filename data contained in Info object { // Create an output archive std::ofstream ofs( "store.dat" ); boost::archive::text_oarchive ar(ofs); // Save the data ar & info; } // Restore from saved data and print to verify contents Info restored_info; { // Create and input archive std::ifstream ifs( "store.dat" ); boost::archive::text_iarchive ar( ifs ); // Load the data ar & restored_info; } restored_info.Print(); return 0; } [/code] Giving you the following output from the restored Info data: ThisFile.txt ThatFile.txt OtherFile.txt Listing 3: Saving and loading multiple objects The same as listing 2, but what if we wish to save multiple versions of the Info object. This shows you how: [code language="cpp"] #include <iostream> #include <vector> #include <fstream> #include <boost/serialization/vector.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/split_member.hpp> class Info { private: // Allow serialization to access non-public data members. friend class boost::serialization::access; template<class Archive> void save(Archive & ar, const unsigned int version) const { ar & filenames; } template<class Archive> void load(Archive & ar, const unsigned int version) { ar & filenames; } BOOST_SERIALIZATION_SPLIT_MEMBER() std::vector<std::string> filenames; public: void AddFilename( const std::string& filename ); void Print() const; }; void Info::Print() const { std::copy(filenames.begin(), filenames.end(), std::ostream_iterator<std::string>(std::cout, "\n")); } void Info::AddFilename( const std::string& filename ) { filenames.push_back( filename ); } int main(int argc, char** argv) { std::vector<Info> infs; Info info1, info2; info1.AddFilename( "ThisFile.txt" ); info2.AddFilename( "ThatFile.txt" ); info2.AddFilename( "OtherFile.txt" ); info2.AddFilename( "ABC" ); info2.AddFilename( "123" ); info2.AddFilename( "XYZ" ); infs.push_back( info1 ); infs.push_back( info2 ); // Save filename data contained in Info object { // Create an output archive std::ofstream ofs( "store.dat" ); boost::archive::text_oarchive ar(ofs); // Save the data ar & infs; } // Restore from saved data and print to verify contents std::vector<Info> restored_info; { // Create and input archive std::ifstream ifs( "store.dat" ); boost::archive::text_iarchive ar( ifs ); // Load the data ar & restored_info; } std::vector<Info>::const_iterator it = restored_info.begin(); for (; it != restored_info.end(); ++it) { Info info = *it; info.Print(); } return 0; } [/code] Giving the following output: BoostSerialize Related post: Serializing data in MFC / Visual C++

Comments

Popular posts from this blog

Using the Supervisor Controller Pattern to access View controls in MVVM

Getting started with client-server applications in C++

How to send an e-mail via Google SMTP using C#