使用CArchive进行数据串行化非常的方便。
CArchive持有一个CFile对象,通过此对象进行读写,那么所有基于CFile的子类,都可以使用CArchive来进行串行化。
示例:
CFile file(_T("1.txt"), CFile::modeReadWrite); CArchive ar(&file, CArchive::load);
此时CArchive对象就是处于读取的状态,我们可以直接通过ar >> obj进行读取。
这里有一个要求,就是obj的类型必须是已经实现的operator >> 重载的类型。像CString,int,double这种,CArchive都已经实现了,可以直接使用。
这里有一个注意就是CArchive在串行化的时候,会向输出中添加以下其他信息,用来识别数据的类型,版本等。
那么来看一下如何让自定义的类型支持串行化,自定义的类型实现串行化,这里主要依靠operator >> 重载的CObject*的串行化版本。那么所有基于CObject的子类都可以实现串行化。
class MyDoc : public CObject { DECLARE_SERIAL(MyDoc); public: MyDoc() = default; MyDoc(int i, CString str); int m_i = 0; CString m_str = _T(""); public: virtual void Serialize(CArchive& ar); };
这里主要是有三点是必须要做的:
1、继承CObject
2、实现宏 DECLARE_SERIAL(MyDoc);
3、重现CObject的虚函数 virtual void Serialize(CArchive& ar);
4、编写默认构造函数。
#include "MyDoc.h" IMPLEMENT_SERIAL(MyDoc, CObject, 1 | VERSIONABLE_SCHEMA); MyDoc::MyDoc(int i, CString str):m_i(i),m_str(str) { } void MyDoc::Serialize(CArchive& ar) { CObject::Serialize(ar); if (ar.IsStoring()) { // storing code ar << m_i << m_str; } else { // loading code UINT schema = ar.GetObjectSchema(); switch (schema) { case 1: ar >> m_i >> m_str; break; default: AfxThrowArchiveException(CArchiveException::badSchema); break; } } }
首先看一下, IMPLEMENT_SERIAL(MyDoc, CObject, 1 | VERSIONABLE_SCHEMA); 这句话的意思,
此宏是DECLARE_SERIAL(MyDoc);的定义实现,通过前两个参数实现MyDoc与CObject的链接,后面1是版本号,宏VERSIONABLE_SCHEMA表示版本号是可变的。
版本号是什么意思呢,就是说如果我们的MyDoc对象在后期增加了数据成员,由于之前串行化的数据没有这个成员,那么版本号就起作用了,我们可以读取文件的版本号,来选择如何反序列化对象。如果老版本的串行化没有后期增加的数据成员,这里只需要反序列化已经有的数据,没有的做单独的初始化即可。
看一下虚函数的实现:
虚函数的实现首先串行化基类CObect对象,然后再串行化自身,这是常规的方式。
对于要序列化的MyDoc对象,这里可以直接使用CArchive对象进行串行化写入,那么在读取时,需要先获取文件的版本号,根据版本号进行操作。
下面是具体的使用例子:将MyDoc对象串行化。
try { CFile file(_T("1.txt"), CFile::modeReadWrite); CArchive ar(&file, CArchive::store); MyDoc* doc = new MyDoc(666,_T("hello,word!")); ar << doc; ar.Flush(); delete doc; } catch (CArchiveException* e) { e->ReportError(); e->Delete(); }
然后将对象反序列化:
try { CFile file(_T("1.txt"), CFile::modeReadWrite); CArchive ar(&file, CArchive::load); MyDoc* doc = new MyDoc; ar >> doc; // 处理doc //。。。。。。。。。。。 delete doc; } catch (CArchiveException* e) { e->ReportError(); e->Delete(); }
CArchive在串行化基于CObject的子类时,要注意,一定是指针,在反序列化时,对象必须时基于堆上的内存指针。
标签:CFile,MFC,CArchive,ar,CObject,MyDoc,串行化 From: https://www.cnblogs.com/Super-biscuits/p/17948177