畅游C++ Boost Serialization 序列化

畅游C++ Boost Serialization 序列化

目录


1.工作环境

2.使用方法

3.工程下载

4.总结

5.参考文献

6.更新

7.C++ Boost::serialization简介


内容

1.工作环境

        VS2010 C++,Windows 7,Boost _1_55_0


2.使用方法

       1.到Boost官网下载对应操作系统平台下的Boost库,此库需要进行编译以生成“静态”和“共享”库。具体编译方法请上网搜索;

       2.包含解压后的头文件路径到工程中:VS2010|选择工程|属性|配置属性|VC++目录|

                              包含目录|添加“D:\C++\Boost\boost_1_55_0”    —— boost库头文件路径

                              库目录|添加“D:\C++\Boost\boost_1_55_0\stage\lib”  —— boost库.lib或.dll文件路径


2.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();
}

2.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>


2.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>


2.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>

2.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>

2.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();
}

2.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>


2.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

2.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>

2.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>

2.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>

2.12将serialize拆分成save和load

        有时候,您不想使用同样的 serialize 方法来转储和恢复对象。在这种情况下,您可以将 serialize 方法拆分成两个方法,即saveload,它们具有类似的签名。这两个方法都是之前定义的serialize 方法的一部分。此外,需要添加BOOST_SERIALIZATION_SPLIT_MEMBER 宏作为类定义的一部分。(引用参考文献[1])

// 清单21

#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);
// 	}
        //将serialize函数分割成save和load函数,两个者实现的效果是等价的
	template<class Archive>
	void save(Archive& archive, const unsigned int version) const //注意 save 方法签名后的 const。如果没有 const 限定符,该代码将无法编译
	{
		archive << BOOST_SERIALIZATION_NVP(m_day);
		archive << BOOST_SERIALIZATION_NVP(m_month);
		archive << BOOST_SERIALIZATION_NVP(m_year);
	} 

	template<class Archive>
	void load(Archive& archive, const unsigned int version)
	{
		archive >> BOOST_SERIALIZATION_NVP(m_day);
		archive >> BOOST_SERIALIZATION_NVP(m_month);
		archive >> BOOST_SERIALIZATION_NVP(m_year);
	} 
	BOOST_SERIALIZATION_SPLIT_MEMBER( ) // must be part of class
}date;

void save( )
{
	std::ofstream file("archive.xml");
	boost::archive::xml_oarchive oa(file);
	date d(15, 8, 1991);
	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();
}

2.13了解Boost::serialize的版本控制

    serializesaveload 的方法签名都使用无符号整数版本作为最后一个参数。这些数字有什么用?随着时间变化,类的内部变量名称可能发生变化,添加新的字段或移除已有字段,等等。这是软件开发过程中的自然进程,除了归档文件仍然保存着关于数据类型原有状态的信息。为了规避这个问题,需要使用版本号。(引用参考文献[1])

        在date类的基础上增加一个unsigned int  ver变量用于保存当前类Mydate的版本号。

// 清单22

#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 << endl;
		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;
BOOST_CLASS_VERSION(date,0);

// Mydate
typedef struct Mydate
{
	unsigned int m_day;
	unsigned int m_month;
	unsigned int m_year;
	unsigned int ver;  //版本

	Mydate(int d, int m, int y, int version):m_day(d), m_month(m) ,m_year(y), ver(version) {  }
	Mydate( ):m_day(1),m_month(1),m_year(2000),ver(1) { }
	friend std::ostream& operator << (std::ostream& out, Mydate& d)
	{
		out << "day:" << d.m_day << "month:" << d.m_month << "year:" << d.m_year << " -- Version:" << d.ver << endl;
		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);
		if(version == 1)
		{
			archive & BOOST_SERIALIZATION_NVP(ver);
		}
	}
}Mydate;
BOOST_CLASS_VERSION(Mydate,1);

void save( )
{
	std::ofstream file("version.xml");
	boost::archive::xml_oarchive oa(file);
	date d(15, 8, 1947);
	oa & BOOST_SERIALIZATION_NVP(d);
	Mydate myd(1, 1, 1991, 1);
	oa & BOOST_SERIALIZATION_NVP(myd);
}

void load( )
{
	std::ifstream file("version.xml");
	boost::archive::xml_iarchive ia(file);
	date dr;
	ia >> BOOST_SERIALIZATION_NVP(dr);
	Mydate myd;
	ia >> BOOST_SERIALIZATION_NVP(myd);
	std::cout << dr;
	std::cout << myd;
}

int main(void)
{
	save();
	load();
	getchar();
}

运行结果:

day:15month:8year:1947
day:1month:1year:1991 -- Version:1

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>
<myd class_id="1" tracking_level="0" version="1">
	<m_day>1</m_day>
	<m_month>1</m_month>
	<m_year>1991</m_year>
	<ver>1</ver>
</myd>
</boost_serialization>

2.14 使用共享指针boost::shared_ptr执行“转储-恢复”操作

// 清单23 

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>  //缺此头文件 —— error C2039: “serialize”: 不是“boost::shared_ptr<T>”的成员	d:\c++\boost\boost_1_55_0\boost\serialization\access.hpp


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("shared_ptr.xml");
	boost::archive::xml_oarchive oa(file);
	boost::shared_ptr<date> d (new date(15, 8, 1947));
	oa & BOOST_SERIALIZATION_NVP(d);
	// other code bellow
}

void load()
{
	std::fstream file("shared_ptr.xml");
	boost::archive::xml_iarchive ia(file);
	boost::shared_ptr<date> dr;
	ia & BOOST_SERIALIZATION_NVP(dr);
	std::cout << *dr;
}

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">
<d class_id="0" tracking_level="0" version="1">
	<px class_id="1" tracking_level="1" version="0" object_id="_0">
		<m_day>15</m_day>
		<m_month>8</m_month>
		<m_year>1947</m_year>
	</px>
</d>
</boost_serialization>


2.15 指向栈对象的指针需要在实际对象之后转储

// 清单24 

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>  //缺此头文件 —— error C2039: “serialize”: 不是“boost::shared_ptr<T>”的成员	d:\c++\boost\boost_1_55_0\boost\serialization\access.hpp


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("stackobject.xml");
	boost::archive::xml_oarchive oa(file);
	date d(1,1,1991);
	date *d2 = &d;
	oa & BOOST_SERIALIZATION_NVP(d);  
	oa & BOOST_SERIALIZATION_NVP(d2);  //指向栈对象的指针需要在实际对象之后转储
}

void load()
{
	std::fstream file("stackobject.xml");
	boost::archive::xml_iarchive ia(file);
	date dr;
	ia & BOOST_SERIALIZATION_NVP(dr);
	std::cout << dr << std::endl;
	date *dr2;
	ia & BOOST_SERIALIZATION_NVP(dr2);
	std::cout << *dr2 << 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">
<d class_id="0" tracking_level="1" version="0" object_id="_0">
<m_day>1</m_day>
<m_month>1</m_month>
<m_year>1991</m_year>
</d>
<d2 class_id_reference="0" object_id_reference="_0"></d2>
</boost_serialization>
           如果有多个指针指向同一个对象,Serialization 会使用 class_id_reference 将指针与原对象关联起来(每个对象都有一个唯一的类 ID)。原对象的每个后续指针都会将 object_id_reference 改成 _1、_2,以此类推。


3.工程下载

        整个工程的下载地址,点此处


4.总结



5.参考文献

[1]. 《Boost Serialization 库》 http://www.ibm.com/developerworks/cn/aix/library/au-boostserialization/


6.更新

2015-05-10  第一次更新   全文开始,增加2.1~2.7 部分内容

2015-05-11  第二次更新    增加2.8~2.13部分内容

2015-05-14  第三次更新    增加2.14~2.15部分内容

2015-05-19  第四次更新    提供工程下载


7.C++ Boost::serialization简介

以下内容引用Boost库的“libs/serialization/doc/index.html”页面:    

         Here, we use the term "serialization" to meanthe reversible deconstruction of an arbitrary set of C++ data structuresto a sequence of bytes. Such a system can be used to reconstitutean equivalent structure in another program context. Depending onthe context, this might used implement object persistence, remoteparameter passing or other facility. In this system we use the term"archive" to refer to a specific rendering of thisstream of bytes. This could be a file of binary data, text data, XML, or some other created by the user of this library.

Our goals for such a system are:

  1. Code portability - depend only on ANSI C++ facilities.
  2. Code economy - exploit features of C++ such as RTTI, templates, and multiple inheritance, etc. where appropriate to make code shorter and simpler to use.
  3. Independent versioning for each class definition. That is, when a class definition changed, older files can still be imported to the new version of the class.
  4. Deep pointer save and restore. That is, save and restore of pointers saves and restores the data pointed to.
  5. Proper restoration of pointers to shared data.
  6. Serialization of STL containers and other commonly used templates.
  7. Data Portability - Streams of bytes created on one platform should be readable on any other.
  8. Orthogonal specification of class serialization and archive format. That is, any file format should be able to store serialization of any arbitrary set of C++ data structures without having to alter the serialization of any class.
  9. Non-intrusive. Permit serialization to be applied to unaltered classes. That is, don't require that classes to be serialized be derived from a specific base class or implement specified member functions. This is necessary to easily permit serialization to be applied to classes from class libraries that we cannot or don't want to have to alter.
  10. The archive interface must be simple enough to easily permit creation of a new type of archive.
  11. The archive interface must be rich enough to permit the creation of anarchive that presents serialized data as XML in a useful manner.

Other implementations

Before getting started I searched around for current implementations. I found several.
  • MFC This is the one that I am very familiar with. I have used it for several years and have found it very useful. However it fails requirements 1, 2, 3, 6, 7, and 9. In spite of all the requirements not fulfilled, this is the most useful implementation I've found. It turns out that class versioning - partially implemented in MFC - really is indispensable for my applications. Inevitably, version 1.x of a shipping program needs to store more information in files than was originally provided for. MFC is the only one of these implementations that supports this - though only for the most derived class. Still it's better than nothing and does the job. MFC doesn't implement serialization of STL collections. Though it does so for MFC collections.
  • CommonC++ libraries [1] As far as I can tell, this closely follows the MFC implementation but does address a few of the issues. It is portable and creates portable archives but skips versioning. It does support proper and complete restoration of pointers and STL collections. It does address compression though not in the way that I would prefer. The package would also benefit from having better documentation. So it fails to address 2, 3, 7, 8, and 9.
  • Eternity [2] This is a bare bones package. It seems well coded but it really needs documentation and examples. It's not obvious how to use it without time consuming study of the source code. Recent versions do support files in XML format. This Fails 3, 6, 7?, 8, and 9.
  • Holub's implementation [3] This is the article that first got me thinking about my own requirements for a serialization implementation. Interesting and worth the read if you can overlook the arrogant tone of the prose. This implementation fails 2, 3, 4, 5, and 6.
  • s11n [13] This library has similar goals to this one. Some aspects of the implemenation are also similar. As of this writing, it would seem that:
    • Portability(1) is guarenteed only for recent versions of GCC.
    • Versioning(3) of class definitions is not explicitly supported by the library.
    • it doesn't seem to automatically account for shared pointers(5). I concluded this from the documentation as well as the statement that serialization of graph like structures is not supported.
    Its has lots of differences - and lots in common with this implementation.





©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值