您的位置:首页 > 其它

使用MFC::CArchive

2011-08-12 10:49 489 查看
转自:http://www.cnblogs.com/ylhome/archive/2010/03/15/1686558.html



使用MFC::CArchive

准确地说,CArchive也属于二进制变长数据,由于CArchive采用了CObject的RTTI特性,同时存储了对象类的信息,因此它对于CObject对象的持久化和反持久化来说,的确是"很好很强大"。

早在第3章我们结合CObject讨论过CArchive的相关知识,要想用上CArchive的强大功能,我们需要做的仅仅是将自己的类定义成支持自创建的CObject子类,并且覆盖默认的Serialize()函数。

现在动手

以下我们将准备一个示例,使用CArchive实现CPerson对象的持久化和反持久化。

选择【Win32】→【Win32项目】→【控制台程序】命令,创建ArchiveTest。

新建CPerson类,CPerson的定义如下:

class CPerson : public CObject  
{  
DECLARE_SERIAL(CPerson)  
private:  
    CString _name;  
    int _age;  
    bool _gender;  
    CString _words;  
public:  
    CPerson();  
    CPerson(CString name, int age, bool gender = true);  
    CString getName();  
    CString getWords();  
    void setWords(CString words);  
    int getAge();  
    bool isMale();  
    void say();  
    void say(CString msg);  
    virtual void Serialize(CArchive& ar);  
};

CPerson类的实现如下:

#include "stdafx.h"  
#include "mfc-person.h"  
 
IMPLEMENT_SERIAL(CPerson, CObject, 1)  
 
CPerson::CPerson()  
{  
    _name = _T("无名氏");  
    _age = 0;  
    _gender = true;  
}  
 
CPerson::CPerson(CString name, int age, bool gender)  
{  
    _name = name;  
    _age = age;  
    _gender = gender;  
}  
 
CString CPerson::getName()  
{  
    return _name;  
}  
 
CString CPerson::getWords()  
{  
    return _words;  
}  
 
void CPerson::setWords(CString words)  
{  
    _words = words;  
}  
 
int CPerson::getAge()  
{  
    return _age;  
}  
 
bool CPerson::isMale()  
{  
    return _gender;  
}  
 
void CPerson::say()  
{  
    say(_words);  
}  
 
void CPerson::say(CString msg)  
{  
    _tprintf(_T("%s: %s\r\n"), _name, msg);  
}  
 
void CPerson::Serialize(CArchive& ar)  
{  
    if (ar.IsStoring())  
    {  
        ar << this->_name<<this->_age<<this->_gender << this->_words;  
    }  
    else 
    {  
        ar >> this->_name>>this->_age>>this->_gender >> this->_words;  
    }  
}

修改主程序,在main()中创建两个CPerson对象,然后将其持久化到文件中,再将其从文件中反持久化出来,调用对象的方法,试试它们还是不是活的:

#include "stdafx.h"  
#include "mfc-person.h"  
#include "ArchiveTest.h"  
 
int main()  
{  
    setlocale(LC_ALL, "chs");  
 
    //创建两个待写入的对象  
    CPerson tong(_T("佟湘玉"), 28, false);  
    tong.setWords(_T("额滴神啊..."));  
 
    CPerson bai(_T("白展堂"), 27, true);  
    bai.setWords(_T("葵花点穴手!"));  
 
    //准备写入  
    CFile oFile(_T("persons.archive"),CFile::
modeCreate|CFile::modeWrite);  
    CArchive oar(&oFile, CArchive::store);  
 
    //序列化进去了  
    oar << &tong << &bai;  
    //oar.WriteObject(&tong);  
    //oar.WriteObject(&bai);  
 
    oar.Close();  
    oFile.Close();  
 
    //准备读取  
    CFile iFile(_T("persons.archive"), CFile::modeRead);  
    CArchive iar(&iFile, CArchive::load);  
 
    CPerson *p1, * p2;  
 
    //序列化出来了  
    iar >> p1 >> p2;  
    //p1 = iar.ReadObject(RUNTIME_CLASS(CPerson));  
    //p2 = iar.ReadObject(RUNTIME_CLASS(CPerson));  
 
    //看看他们是不是活的*_*ii  
    p1->say();  
    p2->say();  
 
    delete p1;  
    delete p2;  
}

运行结果如图6-19所示,可以看出,作为被序列化的CPerson对象,佟掌柜和老白完完全全活过来了。


图6-19 运行结果
比较好奇的读者可以查看一下其生成的二进制文件,这个persons.archive看起来比较乱,但根据运行结果中佟湘玉和白展堂说的两句话,我们不必担心该存储方式的准确性,CArchive生成的二进制内容如图6-20所示。


(点击查看大图)图6-20 CArchive生成的二进制内容
还有一个问题:为什么我们可以使用"oar << &tong << &bai"和"iar >> p1 >> p2"? 实际上CArchive包含了支持"CObject *"参数的流操作符:

_AFX_INLINE CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb)  
{  
    ar.WriteObject(pOb);  
    return ar;  
}  
 
_AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar, CObject*& pOb)  
{  
    pOb = ar.ReadObject(NULL);  
    return ar;  
}

感兴趣的程序员可以究根求源,打开CArchive的源码,就会发现WriteObject()和ReadObject()会反过来调用CObject的Serialize()函数,调用流程如图6-21所示。



(点击查看大图)图6-21 CArchive的调用流程
这正是MFC的精妙之处,它让CPerson不知不觉地就具备了的持久化和反持久化的功能。

===========================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: