简体   繁体   中英

Boost Serialization, need help understanding

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;
}

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:

Live On Coliru

#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 because ofs was declared outside that scope block. This difference is important .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM