I've attached the boost sample serialization code below. I see that they create an output archive and then write the class to the output archive. Then later, they create an input archive and read from the input archive into a new class instance. My question is, how does the input archive know which output archive its reading data from? For example, say I have multiple output archives. How does the input archive that is created know which output archive to read from? I'm not understanding how this is working. Thanks for your help!
#include <fstream>
// include headers that implement a archive in simple text format
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
/////////////////////////////////////////////////////////////
// gps coordinate
//
// illustrates serialization for a simple type
//
class gps_position
{
private:
friend class boost::serialization::access;
// When the class Archive corresponds to an output archive, the
// & operator is defined similar to <<. Likewise, when the class Archive
// is a type of input archive the & operator is defined similar to >>.
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & degrees;
ar & minutes;
ar & seconds;
}
int degrees;
int minutes;
float seconds;
public:
gps_position(){};
gps_position(int d, int m, float s) :
degrees(d), minutes(m), seconds(s)
{}
};
int main() {
// create and open a character archive for output
std::ofstream ofs("filename");
// create class instance
const gps_position g(35, 59, 24.567f);
// save data to archive
{
boost::archive::text_oarchive oa(ofs);
// write class instance to archive
oa << g;
// archive and stream closed when destructors are called
}
// ... some time later restore the class instance to its orginal state
gps_position newg;
{
// create and open an archive for input
std::ifstream ifs("filename");
boost::archive::text_iarchive ia(ifs);
// read class state from archive
ia >> newg;
// archive and stream closed when destructors are called
}
return 0;
}
Example 2
void save_load_with_binary_archive()
{
// binary archive with stringstream
std::ostringstream oss;
boost::archive::binary_oarchive oa(oss);
Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;
oa & (cam);
// get binary content
std::string str_data = oss.str();
std::istringstream iss(str_data);
boost::archive::binary_iarchive ia(iss);
Camera new_cam;
ia & (new_cam);
std::cout << new_cam << std::endl;
}
CodePudding user response:
Like others said, you can set up a stream from existing content. That can be from memory (say istringstream
) or from a file (say ifstream
).
All that matters is what content you stream from. Here's you first example modified to save 10 different streams, which can be read back in any order, or not at all:
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <fstream>
#include <iostream>
/////////////////////////////////////////////////////////////
// gps coordinate
//
// illustrates serialization for a simple type
//
class gps_position {
public:
gps_position(int d = 0, int m = 0, float s = 0)
: degrees(d)
, minutes(m)
, seconds(s) {}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned )
{
ar& degrees& minutes& seconds;
}
int degrees;
int minutes;
float seconds;
friend std::ostream& operator<<(std::ostream& os, gps_position const& gps) {
return os << gps.degrees << "°" << gps.minutes << "′" << gps.seconds << "″";
}
};
int main() {
for (int i = 1; i <= 10; i) {
gps_position const g(7 * i, 12 * i - 1, i * 24.567f / 5);
// save data to archive
{
std::ofstream ofs("filename" std::to_string(i));
boost::archive::text_oarchive oa(ofs);
// write class instance to archive
oa << g;
}
}
for (int i = 10; i > 0; --i) {
// create and open an archive for input
std::ifstream ifs("filename" std::to_string(i));
boost::archive::text_iarchive ia(ifs);
gps_position newg;
ia >> newg;
std::cout << " i:" << i << " - " << newg << "\n";
}
}
Prints
i:10 - 70°119′49.134″
i:9 - 63°107′44.2206″
i:8 - 56°95′39.3072″
i:7 - 49°83′34.3938″
i:6 - 42°71′29.4804″
i:5 - 35°59′24.567″
i:4 - 28°47′19.6536″
i:3 - 21°35′14.7402″
i:2 - 14°23′9.8268″
i:1 - 7°11′4.9134″
After finishing, the contents of each stream will persist in the files:
==> filename1 <==
22 serialization::archive 19 0 0 7 11 4.913399696e 00
==> filename10 <==
22 serialization::archive 19 0 0 70 119 4.913399887e 01
==> filename2 <==
22 serialization::archive 19 0 0 14 23 9.826799393e 00
==> filename3 <==
22 serialization::archive 19 0 0 21 35 1.474019909e 01
==> filename4 <==
22 serialization::archive 19 0 0 28 47 1.965359879e 01
==> filename5 <==
22 serialization::archive 19 0 0 35 59 2.456699944e 01
==> filename6 <==
22 serialization::archive 19 0 0 42 71 2.948039818e 01
==> filename7 <==
22 serialization::archive 19 0 0 49 83 3.439379883e 01
==> filename8 <==
22 serialization::archive 19 0 0 56 95 3.930719757e 01
==> filename9 <==
22 serialization::archive 19 0 0 63 107 4.422060013e 01
SIDENOTE: The comment
// archive and stream closed when destructors are called
was misleading in your question code becauseofs
was declared outside that scope block. This difference is important.