王朝网络
分享
 
 
 

系列化入门读物---PART2

王朝vc·作者佚名  2006-01-08
宽屏版  字体: |||超大  

系列化入门读物

这个指南描述如何轻松地系列化一个简单的对象。

这篇文章包含三个部分。

PART1 介绍基本的系列化

PART2 解释如何有效地读取无效数据和支持版本。

PART3 描述如何对复杂的对象进行系列化。

系列化入门读物-PART2

在Part 1中我们看到了如何通Carchive并利serialize()方法对简单的对象进行系列化,其代码如下:int CFoo::serialize

(CArchive* pArchive)

{

int nStatus = SUCCESS;

// Serialize the object ...

ASSERT (pArchive != NULL);

TRY

{

if (pArchive->IsStoring()) {

// Write employee name and id

(*pArchive) << m_strName;

(*pArchive) << m_nId;

}

else {

// Read employee name and id

(*pArchive) >> m_strName;

(*pArchive) >> m_nId;

}

}

CATCH_ALL (pException)

{

nStatus = ERROR;

}

END_CATCH_ALL

return (nStatus);

}

这段代码有一个问题,就是当我们进行访问的数据并不是我们预期的?如果这个文件中的数据并不是一个Cstring并在其后跟着一个int,我们的serialize()方法将会出错。但这个还好,如果你认可错误并返回一个指定的状态如INVALID_DATAFILE。我们可以通过对象中的标志来来检查我们访问的是否是有效的文件。

Object signatures(对象标志)

对象标志实际上是一个用来识别对象的字符串。我们在Cfoo中加入一个标志: class CFoo

{

...

// Methods

public:

...

CString getSignature();

// Data members

...

protected:

static const CString Signature; // object signature

};

// Static constants

const CString CFoo::Signature = "FooObject";

下一步我们把serialize()修改成在系列化对象的数据成员时先对标志进行系列化。如果发现一个无效的标志或者没有发现标志,表示我们正在尝试读一个并不包含Cfoo对象的文件。下面是读取一个带标志的对象的逻辑图:

下面是代码:

int CFoo::serialize

(CArchive* pArchive)

{

int nStatus = SUCCESS;

bool bSignatureRead = false;

// Serialize the object ...

ASSERT (pArchive != NULL);

TRY

{

if (pArchive->IsStoring()) {

// Write signature

(*pArchive) << getSignature();

// Write employee name and id

(*pArchive) << m_strName;

(*pArchive) << m_nId;

}

else {

// Read signature - complain if invalid

CString strSignature;

(*pArchive) >> strSignature;

bSignatureRead = true;

if (strSignature.Compare (getSignature()) != 0) {

return (INVALID_DATAFILE);

}

// Read employee name and id

(*pArchive) >> m_strName;

(*pArchive) >> m_nId;

}

}

CATCH_ALL (pException)

{

nStatus = bSignatureRead ? ERROR : INVALID_DATAFILE;

}

END_CATCH_ALL

return (nStatus);

}

你需要保证你的所有对象都有相同的标志,实际标志是什么并不是很重要。如果你开发一组产品进,使用相近的对像标志将对你很有帮助。另外,开发者不要误解为对不同的对象也使用相同的标志。如果你要使你的数据文件很难做回逆设计,你需你使用与对象名字没有明显联系的标志。

Versioning(版本)

在产品的生命周期你要对其进行更新,你可能会发现你必需对CFOO的进行添加或删除成员。如果你完全发行一个Cfoo新的版,当尝试对旧的版本的对象进行存取时将会失败。这个是明显不能接受的。任何一个新版的Cfoo必需可以对其以前版本的对象进行系列化,换名话说,就是Cfoo的serialize()方法要可以对以前的可兼容的版本进行操作。我们很容易就可以实现对象的版本化,正如我们对对象加入一个标志一样,我们加入一个整型常量来表示版本号。

class CFoo

{

...

// Methods

public:

...

CString getSignature();

int getVersion();

// Data members

...

protected:

static const CString Signature; // object signature

static const int Version; // object version

};

对象版本在Foo.cpp中进行定义。

// Static constants

const CString CFoo::Signature = "FooObject";

const int CFoo::Version = 1;

下一步,我们把对版本的系列化加入到标志系列化之后且在成员数据系列化之前。如果遇到新的版本或者读取一个不支持的版本,在这些情况下,我们简单地返回UNSUPPORTED_VERSION状态。

int CFoo::serialize

(CArchive* pArchive)

{

int nStatus = SUCCESS;

bool bSignatureRead = false;

bool bVersionRead = false;

// Serialize the object ...

ASSERT (pArchive != NULL);

TRY

{

if (pArchive->IsStoring()) {

// Write signature and version

(*pArchive) << getSignature();

(*pArchive) << getVersion();

// Write employee name and id

(*pArchive) << m_strName;

(*pArchive) << m_nId;

}

else {

// Read signature - complain if invalid

CString strSignature;

(*pArchive) >> strSignature;

bSignatureRead = true;

if (strSignature.Compare (getSignature()) != 0) {

return (INVALID_DATAFILE);

}

// Read version - complain if unsupported

int nVersion;

(*pArchive) >> nVersion;

bVersionRead = true;

if (nVersion > getVersion()) {

return (UNSUPPORTED_VERSION);

}

// Read employee name and id

(*pArchive) >> m_strName;

(*pArchive) >> m_nId;

}

}

CATCH_ALL (pException)

{

nStatus = bSignatureRead && bVersionRead ? ERROR : INVALID_DATAFILE;

}

END_CATCH_ALL

return (nStatus);

}

在版本1中我们的Cfoo包含两个数据成员(m_strName和m_nId)。如果我们在版本2中加入第三个成员(int m_nDept),我们需要决定在读取旧版本时m_nDept初始化成什么值。在这个例子中,我们初始化为-1,这意味着职工的部门代码是未知的。

class CFoo

{

...

// Data members

public:

CString m_strName; // employee name

int m_nId; // employee id

int m_nDept; // department code (-1 = unknown)

};

我们同样需要在Foo.cpp中加入版本标志并设为2。

const int CFoo::Version = 2;

最后,我们需要修改serialize()中的读取数据部分,因为当读取旧版本时我们要对m_nDept进行初始化。注意文件保存时始终保存为最新版的。

int CFoo::serialize

(CArchive* pArchive)

{

...

// Serialize the object ...

ASSERT (pArchive != NULL);

TRY

{

if (pArchive->IsStoring()) {

...

// Write employee name, id and department code

(*pArchive) << m_strName;

(*pArchive) << m_nId;

(*pArchive) << m_nDept;

}

else {

...

// Read employee name and id

(*pArchive) >> m_strName;

(*pArchive) >> m_nId;

// Read department code (new in version 2)

if (nVersion >= 2) {

(*pArchive) >> m_nDept;

}

else {

m_nDept = -1; // unknown

}

}

}

CATCH_ALL (pException)

{

nStatus = bSignatureRead && bVersionRead ? ERROR : INVALID_DATAFILE;

}

END_CATCH_ALL

return (nStatus);

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有