畅游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 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 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 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>
// 清单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>
// 清单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.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
// 清单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 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 第一次更新
原文地址:http://blog.csdn.net/qq2399431200/article/details/45621921