boost serialization 试用
年底了,项目要验收,整天的加班,实在是没有时间写点东西。
前段时间参加苏州。net 俱乐部第一次活动。活动还时非常有意思的。
。net 社群的活跃让我非常感慨,这是一个年轻的社群,充满激情,
充满求知欲望,充满创造性!
我参加这个活动还真有点不好意思。原因是有段时间不写c# 代码了。
现在用什么语言基本是工作需要。当然我本人还是非常喜欢c# 的。也在这方面
投入了非常大的时间和精力。要说的是,这段时间不写c# 的东西不代表我倒阁去
了c++(目前的工作用c++),c# 将是我一身坚持的东西!只要有时间我就会看看。
言规正转。最近一段都在研究boost,自己写的一些东西需要用到里面的东西。
这两周看了下boost 中关于序列化的部分。讲到序列化 c# 的朋友都不陌生。因为这个机制是语言本事支持的(通过反射机制支持)。该机制通过原数据动态获取运行时类型的信息,从而获取到了足够的信息序列化到磁盘等设备上。System.Xml.Serialization;下的XmlSerializer类型提供了对xml 序列化的基本支持。以前的我的几个任务都涉及到序列化/反序列。需求基本是这样的:
1。把数据库中的游戏角色数据导出到xml 文件。
2。修改改游戏角色的部分数据后导回到数据库。
这个像不像外挂?呵呵,我觉得比外挂强,至少比外挂能操作的数据多。 当时遇到的问题是HashTable 类型序列化的时候需要自己复写一些接口,比较麻烦。后来到老外那里淘了个库,并在这个基础上封装了两个接口,基本上可以对任意类型序列化。共享代码如下:
/Files/dxfcv222/Serialize.rar
c++下就没有这么幸运了。语言本身不支持反射机制,无法动态获取类型信息。
boost 库中也有关于元编程的支持,这个还不太了解如何实现的,暂时不做讨论。boost/Serialization 能够解决序列化,反序列化问题。请看下面代码:
template<class Archive>
void save(Archive & ar, const unsigned int version) const
接口完成序列化,
template<class Archive>
void load(Archive & ar, const unsigned int version)
接口完成反序列化。
BOOST_CLASS_VERSION(a, 2)
指定该类型序列化的版本,如果以后该类型发生变化,可以根据版本情况选择性的
加载数据。
下面是序列化/反序列化的测试代码:
上述代码基本上都是围绕 load save 两个接口展开的。load save 这两个接口完成对象的序列化/反序列化工作。boost/Serialization库的设计者为什么不把这两个接口实现为一个抽象类型,比如ISerializable ,需要具备序列化能力的类型只要复写这两个接口就可以?这样的约束能力比自觉的写load save 函数个人觉得强多了,至少是编译时约束。
我在 laod save 接口中大量使用了BOOST_SERIALIZATION_NVP宏,通过该宏可以给每个要序列化的元素一个名称。因为xml 文件中每个属性都是有名称的。当然也可以把这样写的类型序列化到文本或者是2进制流中,缺点是消耗的字节数比只序列化裸元素要高。这个感兴趣的朋友可以测试下。
当类型具备了序列化能力,我们就可以把它通过网络传输,也可以把对象保存到xml 文件或者是数据库中。
类型序列化能力对游戏开发是非常重要的,游戏玩家角色存储到数据库,通过网络传输自定义消息等都可以通过序列化实现。
前段时间参加苏州。net 俱乐部第一次活动。活动还时非常有意思的。
。net 社群的活跃让我非常感慨,这是一个年轻的社群,充满激情,
充满求知欲望,充满创造性!
我参加这个活动还真有点不好意思。原因是有段时间不写c# 代码了。
现在用什么语言基本是工作需要。当然我本人还是非常喜欢c# 的。也在这方面
投入了非常大的时间和精力。要说的是,这段时间不写c# 的东西不代表我倒阁去
了c++(目前的工作用c++),c# 将是我一身坚持的东西!只要有时间我就会看看。
言规正转。最近一段都在研究boost,自己写的一些东西需要用到里面的东西。
这两周看了下boost 中关于序列化的部分。讲到序列化 c# 的朋友都不陌生。因为这个机制是语言本事支持的(通过反射机制支持)。该机制通过原数据动态获取运行时类型的信息,从而获取到了足够的信息序列化到磁盘等设备上。System.Xml.Serialization;下的XmlSerializer类型提供了对xml 序列化的基本支持。以前的我的几个任务都涉及到序列化/反序列。需求基本是这样的:
1。把数据库中的游戏角色数据导出到xml 文件。
2。修改改游戏角色的部分数据后导回到数据库。
这个像不像外挂?呵呵,我觉得比外挂强,至少比外挂能操作的数据多。 当时遇到的问题是HashTable 类型序列化的时候需要自己复写一些接口,比较麻烦。后来到老外那里淘了个库,并在这个基础上封装了两个接口,基本上可以对任意类型序列化。共享代码如下:
/Files/dxfcv222/Serialize.rar
c++下就没有这么幸运了。语言本身不支持反射机制,无法动态获取类型信息。
boost 库中也有关于元编程的支持,这个还不太了解如何实现的,暂时不做讨论。boost/Serialization 能够解决序列化,反序列化问题。请看下面代码:
1
class a
2
{
3
public:
4
a()
5
{
6
7
}
8
a(int i, float f, double d, string s, wstring ws):
9
i(i),
10
f(f),
11
d(d),
12
s(s),
13
ws(ws)
14
{
15
16
}
17
18
19
template<class Archive>
20
void save(Archive & ar, const unsigned int version) const
21
{
22
ar
23
<< BOOST_SERIALIZATION_NVP(i)
24
<< BOOST_SERIALIZATION_NVP(f)
25
<< BOOST_SERIALIZATION_NVP(d)
26
<< BOOST_SERIALIZATION_NVP(s)
27
<< BOOST_SERIALIZATION_NVP(ws);
28
}
29
30
template<class Archive>
31
void load(Archive & ar, const unsigned int version)
32
{
33
try
34
{
35
if (version > 0)
36
{
37
ar
38
>> BOOST_SERIALIZATION_NVP(i)
39
>> BOOST_SERIALIZATION_NVP(f)
40
>> BOOST_SERIALIZATION_NVP(d)
41
>> BOOST_SERIALIZATION_NVP(s)
42
>> BOOST_SERIALIZATION_NVP(ws);
43
}
44
}
45
catch (exception)
46
{
47
48
throw;
49
}
50
51
}
52
53
friend class boost::serialization::access;
54
BOOST_SERIALIZATION_SPLIT_MEMBER()
55
56
57
public:
58
int i;
59
float f;
60
double d;
61
string s;
62
wstring ws;
63
64
};
65
66
BOOST_CLASS_VERSION(a, 2)
67
BOOST_SERIALIZATION_SHARED_PTR(a)

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

template<class Archive>
void save(Archive & ar, const unsigned int version) const
接口完成序列化,
template<class Archive>
void load(Archive & ar, const unsigned int version)
接口完成反序列化。
BOOST_CLASS_VERSION(a, 2)
指定该类型序列化的版本,如果以后该类型发生变化,可以根据版本情况选择性的
加载数据。
下面是序列化/反序列化的测试代码:
1
2
//写入测试
3
4
{
5
6
std::ofstream ofs("a.txt");
7
//std::ofstream ofs("a.xml");
8
boost::archive::text_oarchive oa(ofs);
9
//boost::archive::xml_oarchive oa(ofs);
10
11
const a a1(1, 2, 3, "dxf", L"dxf");
12
13
oa
14
<< BOOST_SERIALIZATION_NVP(a1);
15
16
}
17
18
19
20
21
//读取测试
22
23
{
24
std::ifstream ifs("a.txt", std::ios::binary);
25
//boost::archive::xml_iarchive ia(ifs);
26
boost::archive::text_iarchive ia(ifs);
27
28
a a1;
29
try
30
{
31
32
ia >> BOOST_SERIALIZATION_NVP(a1);
33
34
35
36
cout << a1.i << endl;
37
cout << a1.f << endl;
38
cout << a1.d << endl;
39
cout << a1.s << endl;
40
41
42
}
43
catch (exception)
44
{
45
}
46
47
}
48
49

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

上述代码基本上都是围绕 load save 两个接口展开的。load save 这两个接口完成对象的序列化/反序列化工作。boost/Serialization库的设计者为什么不把这两个接口实现为一个抽象类型,比如ISerializable ,需要具备序列化能力的类型只要复写这两个接口就可以?这样的约束能力比自觉的写load save 函数个人觉得强多了,至少是编译时约束。
我在 laod save 接口中大量使用了BOOST_SERIALIZATION_NVP宏,通过该宏可以给每个要序列化的元素一个名称。因为xml 文件中每个属性都是有名称的。当然也可以把这样写的类型序列化到文本或者是2进制流中,缺点是消耗的字节数比只序列化裸元素要高。这个感兴趣的朋友可以测试下。
当类型具备了序列化能力,我们就可以把它通过网络传输,也可以把对象保存到xml 文件或者是数据库中。
类型序列化能力对游戏开发是非常重要的,游戏玩家角色存储到数据库,通过网络传输自定义消息等都可以通过序列化实现。