畅游C++ Boost Serialization 序列化
1.C++ Boost::serialization简介
2.工作环境
3.使用方法
3.1第一个简单的例子 —— Hello World ,将字符串内容归档到文本文件中
#include <iostream> #include <fstream> #include <string> #include <cstdio> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> // 清单1.将字符串保存到文本归档文件中 void save() { std::ofstream file("archive.txt"); boost::archive::text_oarchive oa(file); std::string s = "Hello world\n"; oa << s; // oa & s; 清单3.使用&运算符执行“转储-恢复”操作 } // 清单2.将字符串的内容加载到文本文件中 void load() { std::ifstream file("archive.txt"); boost::archive::text_iarchive ia(file); std::string s; ia >> s; // ia & s; 清单3.使用&运算符执行“转储-恢复”操作 std::cout << s << std::endl; } int main() { save(); load(); getchar(); }
3.2从xml文档文件执行“转储-恢复”操作
// 清单4 #include <iostream> #include <fstream> #include <string> #include <cstdio> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> void save() { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); std::string s = "Hello world! 你好,世界!\n"; //如果您想使用 XML 归档文件,而不是文本归档文件,需要将数据打包到一个名为 BOOST_SERIALIZATION_NVP 的宏中 oa & BOOST_SERIALIZATION_NVP(s); } void load() { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); std::string s; ia & BOOST_SERIALIZATION_NVP(s); std::cout << s << std::endl; } int main() { save(); load(); getchar(); }
xml归档文件中的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <s>Hello world! 你好,世界! </s> </boost_serialization>
3.3对整数数组执行“转储-恢复”操作
// 清单6 #include <fstream> #include <iostream> #include <algorithm> #include <iterator> #include <cstdio> #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> void save() { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); int arrary1[ ] = { 34, 78, 22, 1, 910 }; oa & BOOST_SERIALIZATION_NVP(arrary1); } /* 是否可以仅通过指定指针 int* restored 完成此操作并为您恢复数组? 答案是否定的。必须每次都指定大小。如果认真回答此问题的话,答案是对基本 类型的指针进行序列化非常复杂。*/ void load() { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); int restored[5]; //必须指定数组的大小 ia & BOOST_SERIALIZATION_NVP(restored); std::ostream_iterator<int> oi(std::cout, " "); std::copy(restored, restored+5, oi); } int main() { save(); load(); getchar(); }
xml归档文件中的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <arrary1> <count>5</count> <item>34</item> <item>78</item> <item>22</item> <item>1</item> <item>910</item> </arrary1> </boost_serialization>
3.4串行化STL集合
// 清单8 #include <iostream> #include <fstream> #include <algorithm> #include <iterator> #include <cstdio> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> #include <boost/serialization/list.hpp> #include <boost/serialization/vector.hpp> void save( ) { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); float array[ ] = {34.2, 78.1, 22.221, 1.0, -910.88}; std::list<float> L1(array, array+5); std::vector<float> V1(array, array+5); oa & BOOST_SERIALIZATION_NVP(L1); oa & BOOST_SERIALIZATION_NVP(V1); } void load() { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); std::list<float> L2; ia >> BOOST_SERIALIZATION_NVP(L2); //不需要指定范围/大小 std::vector<float> V2; ia >> BOOST_SERIALIZATION_NVP(V2); //不需要指定范围/大小 std::ostream_iterator<float> oi(std::cout, " "); std::copy(L2.begin(), L2.end(), oi ); std::copy(V2.begin(), V2.end(), oi ); } int main() { save(); load(); getchar(); }
xml归档文件中内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <L1> <count>5</count> <item_version>0</item_version> <item>34.200001</item> <item>78.099998</item> <item>22.221001</item> <item>1</item> <item>-910.88</item> </L1> <V1> <count>5</count> <item_version>0</item_version> <item>34.200001</item> <item>78.099998</item> <item>22.221001</item> <item>1</item> <item>-910.88</item> </V1> </boost_serialization>
3.5序列化自己的类型——serialize方法的侵入版本
// 清单10 所谓“侵入”即serialize方法写到类中 #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> namespace { using std::cout; using std::cin; using std::endl; } typedef struct date { unsigned int m_day; unsigned int m_month; unsigned int m_year; date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "month:" << d.m_month << "year:" << d.m_year; return out; } template<typename Archive> void serialize(Archive& archive, const unsigned int version) { archive & BOOST_SERIALIZATION_NVP(m_day); archive & BOOST_SERIALIZATION_NVP(m_month); archive & BOOST_SERIALIZATION_NVP(m_year); } }date; void save( ) { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); date d(15, 8, 1947); oa & BOOST_SERIALIZATION_NVP(d); } void load( ) { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); date dr; ia >> BOOST_SERIALIZATION_NVP(dr); std::cout << dr; } int main(void) { save(); load(); getchar(); }
xml归档文件的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <d class_id="0" tracking_level="0" version="0"> <m_day>15</m_day> <m_month>8</m_month> <m_year>1947</m_year> </d> </boost_serialization>
3.6序列化自己的类型——serialize方法的非侵入版本
// 清单11 所谓“非侵入”即serialize方法不必写在类中、不属于类 #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> namespace { using std::cout; using std::cin; using std::endl; } typedef struct date { unsigned int m_day; unsigned int m_month; unsigned int m_year; date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "month:" << d.m_month << "year:" << d.m_year; return out; } }date; // 序列化相关的类和函数都属于boost::serialization命名空间里,所以自定义的serialize函数也可被其中的其它类和函数调用 namespace boost { namespace serialization { template<typename Archive> void serialize(Archive& archive, date& d, const unsigned int version) { archive & BOOST_SERIALIZATION_NVP(d.m_day); archive & BOOST_SERIALIZATION_NVP(d.m_month); archive & BOOST_SERIALIZATION_NVP(d.m_year); } } } void save( ) { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); date d(15, 8, 1947); oa & BOOST_SERIALIZATION_NVP(d); } void load( ) { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); date dr; ia >> BOOST_SERIALIZATION_NVP(dr); std::cout << dr; } int main(void) { save(); load(); getchar(); }
3.7通过基类指针转储派生类——使用xml文件归档
// 清单13 #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> #include <string> namespace { using std::cout; using std::cin; using std::endl; using std::string; } class CBase { friend class boost::serialization::access; template<typename Archive> void serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_NVP(baseName); } string baseName; public: CBase( ) { baseName = "class CBase"; } virtual ~CBase( ) { } //必须加一个virtual函数,否则“dynamic_cast<date*> (dr)”报error C2683: “dynamic_cast”:“CBase”不是多态类型 错误 //这是C++多态属性决定的 }; class date : public CBase { unsigned int m_day; unsigned int m_month; unsigned int m_year; public: date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "\nmonth:" << d.m_month << "\nyear:" << d.m_year; return out; } virtual ~date() { } private: friend class boost::serialization::access; template<typename Archive> void serialize(Archive& archive, const unsigned int version) { //archive & boost::serialization::base_object<CBase> (*this); //用文本文档归档用此方法,当用于xml归档时会发生error C2664: “boost::mpl::assertion_failed”: 不能将参数 1 从“boost::mpl::failed ************boost::serialization::is_wrapper<T>::* ***********”转换为“boost::mpl::assert<false>::type” archive & BOOST_SERIALIZATION_BASE_OBJECT_NVP(CBase); //用xml归档时,需要将父类对象包装,即用此宏,否则发生如上错误提示 archive & BOOST_SERIALIZATION_NVP(m_day); archive & BOOST_SERIALIZATION_NVP(m_month); archive & BOOST_SERIALIZATION_NVP(m_year); } }; void save( ) { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); oa.register_type<date>(); CBase *b = new date(16, 8, 1947); oa & BOOST_SERIALIZATION_NVP(b); delete b; } void load( ) { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); ia.register_type<date>(); CBase *dr; ia >> BOOST_SERIALIZATION_NVP(dr); date *dr2 = dynamic_cast<date*> (dr); std::cout << *dr2; delete dr2; } int main(void) { save(); getchar(); load(); getchar(); }
xml归档文件的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <b class_id="0" tracking_level="1" version="0" object_id="_0"> <CBase class_id="1" tracking_level="1" version="0" object_id="_1"> <baseName>class CBase</baseName> </CBase> <m_day>16</m_day> <m_month>8</m_month> <m_year>1947</m_year> </b> </boost_serialization>
3.8通过基类指针转储派生类——使用文本文件归档
// 注意和“3.7”的区别 #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> #include <string> namespace { using std::cout; using std::cin; using std::endl; using std::string; } class CBase { friend class boost::serialization::access; template<typename Archive> void serialize(Archive& ar, const unsigned int version) { ar & baseName; } string baseName; public: CBase( ) { baseName = "class CBase"; } virtual ~CBase( ) { } //必须加一个virtual函数,否则“dynamic_cast<date*> (dr)”报error C2683: “dynamic_cast”:“CBase”不是多态类型 错误 //这是C++多态属性决定的 }; class date : public CBase { unsigned int m_day; unsigned int m_month; unsigned int m_year; public: date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "\nmonth:" << d.m_month << "\nyear:" << d.m_year; return out; } virtual ~date() { } private: friend class boost::serialization::access; template<typename Archive> void serialize(Archive& archive, const unsigned int version) { archive & boost::serialization::base_object<CBase> (*this); //用文本文档归档用此方法,当用于xml归档时会发生error C2664: “boost::mpl::assertion_failed”: 不能将参数 1 从“boost::mpl::failed ************boost::serialization::is_wrapper<T>::* ***********”转换为“boost::mpl::assert<false>::type” //archive & BOOST_SERIALIZATION_BASE_OBJECT_NVP(CBase); //用xml归档时,需要将父类对象包装,即用此宏,否则发生如上错误提示 archive & m_day; archive & m_month; archive & m_year; } }; void save( ) { std::ofstream file("archive.txt"); boost::archive::text_oarchive oa(file); oa.register_type<date>(); CBase *b = new date(16, 8, 1947); oa & b; delete b; } void load( ) { std::ifstream file("archive.txt"); boost::archive::text_iarchive ia(file); ia.register_type<date>(); CBase *dr; ia >> dr; date *dr2 = dynamic_cast<date*> (dr); std::cout << *dr2; delete dr2; } int main(void) { save(); getchar(); load(); getchar(); }
文本文件归档内容:
22 serialization::archive 10 0 1 0 0 1 0 1 11 class CBase 16 8 1947
3.9使用指针执行“转储-恢复”操作
// 清单15 #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> namespace { using std::cout; using std::cin; using std::endl; } typedef struct date { unsigned int m_day; unsigned int m_month; unsigned int m_year; date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "month:" << d.m_month << "year:" << d.m_year; return out; } template<typename Archive> void serialize(Archive& archive, const unsigned int version) { archive & BOOST_SERIALIZATION_NVP(m_day); archive & BOOST_SERIALIZATION_NVP(m_month); archive & BOOST_SERIALIZATION_NVP(m_year); } }date; void save( ) { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); date *d = new date(15, 8, 1947); cout << d << endl; oa & BOOST_SERIALIZATION_NVP(d); } void load( ) { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); date *dr; ia >> BOOST_SERIALIZATION_NVP(dr); std::cout << dr << endl; cout << *dr; } int main(void) { save(); load(); getchar(); }
运行结果:
0047A108 0047A6B8 day:15month:8year:1947
xml归档文件中的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <d class_id="0" tracking_level="1" version="0" object_id="_0"> <m_day>15</m_day> <m_month>8</m_month> <m_year>1947</m_year> </d> </boost_serialization>
3.10使用指针执行“转储-恢复”操作——将两个指针转储到同一个对象
// 清单17 #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> namespace { using std::cout; using std::cin; using std::endl; } typedef struct date { unsigned int m_day; unsigned int m_month; unsigned int m_year; date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "month:" << d.m_month << "year:" << d.m_year; return out; } template<typename Archive> void serialize(Archive& archive, const unsigned int version) { archive & BOOST_SERIALIZATION_NVP(m_day); archive & BOOST_SERIALIZATION_NVP(m_month); archive & BOOST_SERIALIZATION_NVP(m_year); } }date; void save() { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); date *d = new date(15,8,1947); cout << d << endl; oa & BOOST_SERIALIZATION_NVP(d); date *d2 = d; oa & BOOST_SERIALIZATION_NVP(d2); } void load() { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); date *dr; ia >> BOOST_SERIALIZATION_NVP(dr); cout << dr << endl; cout << *dr << endl; date *dr2; ia >> BOOST_SERIALIZATION_NVP(dr2); cout << dr2 << endl; cout << *dr2; } int main(void) { save(); load(); getchar(); }
运行结果:
0010A108 0010A6B8 day:15month:8year:1947 0010A6B8 day:15month:8year:1947
xml归档文件中的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <d class_id="0" tracking_level="1" version="0" object_id="_0"> <m_day>15</m_day> <m_month>8</m_month> <m_year>1947</m_year> </d> <d2 class_id_reference="0" object_id_reference="_0"></d2> </boost_serialization>
3.11包含作为d的引用d2的归档文件
// 清单19 和参考网页(IBM)中的那部分不一致 #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <iostream> #include <fstream> #include <cstdio> namespace { using std::cout; using std::cin; using std::endl; } typedef struct date { unsigned int m_day; unsigned int m_month; unsigned int m_year; date(int d, int m, int y):m_day(d), m_month(m) ,m_year(y) { } date( ):m_day(1),m_month(1),m_year(2000) { } friend std::ostream& operator << (std::ostream& out, date& d) { out << "day:" << d.m_day << "month:" << d.m_month << "year:" << d.m_year; return out; } template<typename Archive> void serialize(Archive& archive, const unsigned int version) { archive & BOOST_SERIALIZATION_NVP(m_day); archive & BOOST_SERIALIZATION_NVP(m_month); archive & BOOST_SERIALIZATION_NVP(m_year); } }date; void save() { std::ofstream file("archive.xml"); boost::archive::xml_oarchive oa(file); date *d = new date(15,8,1947); cout << d << endl; oa & BOOST_SERIALIZATION_NVP(d); date* &d2 = d; //d2 reference d oa & BOOST_SERIALIZATION_NVP(d2); } void load() { std::ifstream file("archive.xml"); boost::archive::xml_iarchive ia(file); date *dr; ia >> BOOST_SERIALIZATION_NVP(dr); cout << dr << endl; cout << *dr << endl; date *dr2; ia >> BOOST_SERIALIZATION_NVP(dr2); cout << dr2 << endl; cout << *dr2; } int main(void) { save(); load(); getchar(); }
xml归档文件的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="10"> <d class_id="0" tracking_level="1" version="0" object_id="_0"> <m_day>15</m_day> <m_month>8</m_month> <m_year>1947</m_year> </d> <d2 class_id_reference="0" object_id_reference="_0"></d2> </boost_serialization>
将serialize拆分成save和load
4.总结
5.参考文献
[1]. 《Boost Serialization 库》http://www.ibm.com/developerworks/cn/aix/library/au-boostserialization/
6.更新
2015-05-10 第一次更新
时间: 2024-11-02 02:19:43