読者です 読者をやめる 読者になる 読者になる

Boost.Serializationで遊んでみた

C++

これ使うとXMLの扱いがとっても簡単になりますね


基本的にはシリアライズしたいクラスのメンバにserialize関数を追加するだけです




・テキスト出力

#include <fstream>
#include <string>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>

class Person {
public:
    int         age;
    std::string name;

private:
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& archive, unsigned int version)
    {
        static_cast<void>(version); // No use
        archive & age;
        archive & name;
    }
};

int main()
{
    std::ofstream ofs("C:/person.txt");
    boost::archive::text_oarchive oarchive(ofs);

    Person person;
    person.age  = 22;
    person.name = "Akira";

    // クラス情報をテキスト出力
    oarchive << static_cast<const Person&>(person);

    return 0;
}
22 serialization::archive 4 0 0 22 5 Akira


・テキスト読込(↑で出力されたもの)

#include <iostream>
#include <fstream>
#include <string>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/text_iarchive.hpp>

class Person {
public:
    int         age;
    std::string name;

private:
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& archive, unsigned int version)
    {
        static_cast<void>(version); // No use
        archive & age;
        archive & name;
    }
};

int main()
{
    std::ifstream ifs("C:/person.txt");
    boost::archive::text_iarchive iarchive(ifs);

    // テキスト読込
    Person person;
    iarchive >> person;

    // 読み込んだ内容を表示
    std::cout << person.age << "," << person.name << std::endl;

    return 0;
}
22,Akira


XML出力

boost::serialization::make_nvpで要素名を指定する
それ以外はテキストと同じ

#include <fstream>
#include <string>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/xml_oarchive.hpp>

class Person {
public:
    int         age;
    std::string name;

private:
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& archive, unsigned int version)
    {
        static_cast<void>(version); // No use
        archive & boost::serialization::make_nvp("Age", age);
        archive & boost::serialization::make_nvp("Name", name);
    }
};

int main()
{
    std::ofstream ofs("C:/person.xml");
    boost::archive::xml_oarchive oarchive(ofs);

    Person person;
    person.age  = 22;
    person.name = "Akira";

    // クラス情報をXML出力
    oarchive << boost::serialization::make_nvp("Root", person);

    return 0;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="4">
<Root class_id="0" tracking_level="0" version="0">
	<Age>22</Age>
	<Name>Akira</Name>
</Root>
</boost_serialization>


すばらしく簡単です。

これはもうC#並と言ってもいいのではないかと
(C#のは簡単すぎですね...ずるい)


XML読込(↑で出力したもの)

#include <iostream>
#include <fstream>
#include <string>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/xml_iarchive.hpp>

class Person {
public:
    int         age;
    std::string name;

private:
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& archive, unsigned int version)
    {
        static_cast<void>(version); // No use
        archive & boost::serialization::make_nvp("Age", age);
        archive & boost::serialization::make_nvp("Name", name);
    }
};

int main()
{
    std::ifstream ifs("C:/person.xml");
    boost::archive::xml_iarchive iarchive(ifs);

    // XML読込
    Person person;
    iarchive >> boost::serialization::make_nvp("Root", person);

    // 読み込んだ内容を表示
    std::cout << person.age << "," << person.name << std::endl;

    return 0;
}


XML出力2(要素内要素があるもの...ツリー構造)

#include <fstream>
#include <string>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/xml_oarchive.hpp>

class Body {
public:
    std::string heart; // 心臓

private:
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& archive, unsigned int version)
    {
        static_cast<void>(version); // No use
        archive & boost::serialization::make_nvp("Heart", heart);
    }
};


class Person {
public:
    int         age; // 年齢
    std::string name; // 名前
    Body        body; // 体

private:
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive& archive, unsigned int version)
    {
        static_cast<void>(version); // No use
        archive & boost::serialization::make_nvp("Age", age);
        archive & boost::serialization::make_nvp("Name", name);
        archive & boost::serialization::make_nvp("Body", body);
    }
};

int main()
{
    std::ofstream ofs("C:/person.xml");
    boost::archive::xml_oarchive oarchive(ofs);

    Person person;
    person.age        = 22;
    person.name       = "Akira";
    person.body.heart = "heart";

    // クラス情報をXML出力
    oarchive << boost::serialization::make_nvp("Root", person);

    return 0;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="4">
<Root class_id="0" tracking_level="0" version="0">
	<Age>22</Age>
	<Name>Akira</Name>
	<Body class_id="1" tracking_level="0" version="0">
		<Heart>heart</Heart>
	</Body>
</Root>
</boost_serialization>

ただまァ、ルート要素(boost_serialization)だけジャマですね




以下は試してないですが
・書き込みと読み込みで違う動作をさせたい場合は、
 serialize()ではなくsave()/load()をメンバ関数として作成する

・serialize()/save()/load()の引数versionとBOOST_CLASS_VERSIONを使用してバージョン管理が可能




STLコンテナのシリアライズも可能
std::deque
 

std::list
 

std::map
 

std::set
 

std::basic_string
 

std::valarray
 

std::vector
 

std::pair
 



std::slist
 

std::hash_map
 

std::hash_set
 

boost::optional
 

boost::variant
 

boost::scoped_ptr
 

boost::shared_ptr
 

boost::weak_ptr
 



【参考】
boost::serializationを使う