NanShan 相信说明 VC++ CArchive 如何使用

来源:NanShan 相信说明 VC++ CArchive 如何使用

使用MFC::CArchive
NanShan 即时通讯软件 做事情都喜欢追根究底,今天就来深入了解 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"), _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不知不觉地就具备了的持久化和反持久化的功能。
===========================================



你可能感兴趣的:(二进制,程序员,vc++,控制台,即时通讯)