1. 程式人生 > >MFC介面程式設計基礎(17):文件序列化

MFC介面程式設計基礎(17):文件序列化

上一篇:MFC介面程式設計基礎(16):文件、檢視、框架 下一篇:MFC介面程式設計基礎(18):文件檢視結構應用程式例子(Ex_DocView)

序列化定義

MFC文件-檢視結構中,序列化機制可以實現記憶體中物件儲存和載入
序列化機制分為序列化和反序列化:

  • 序列化是把記憶體中的物件以二進位制檔案的形式儲存在磁碟中
  • 反序列化是把序列化後生成的檔案恢復到記憶體。

CArchive類

CArchive沒有基類。CArchive允許以一個永久二進位制(通常為磁碟儲存)的形式儲存一個物件的複雜網路,它可以在物件被刪除時,還能永久儲存。可以從永久儲存中裝載物件,在記憶體中重新構造它們。使得資料永久保留的過程就叫作 “序列化”。
可以把一個歸檔物件(CArchive)看作一種二進位制流。像輸入/輸出流一樣,歸檔與檔案有關並允許寫緩衝區以及從硬碟讀出或讀入資料。輸入/輸出流處理一系列ASCII字元,但是歸檔檔案以一種有效率、精練的格式處理二進位制物件

CArchive物件處理基礎型別資料

必須在建立一個CArchive物件之前,建立一個CFile物件。另外,必須確信歸檔檔案的裝入/儲存與檔案的開啟模式是相容的。每一個檔案只限於一個活動歸檔檔案。當構造一個CArchive物件時,要把它附加給表示一個開啟檔案的類CFile(或派生類)的物件上。還要指定歸檔檔案將用於裝載還是儲存。

  • 示例:
//將資料以二進位制方式寫入檔案中
void CArchiveView::OnWritefile()
{
	// TODO:  在此新增命令處理程式程式碼
	//構造CFile檔案物件
	CFile file(_T("demo.txt"), 
CFile::modeCreate | CFile::modeWrite);
	//構造存檔物件
	CArchive ar(&file, CArchive::store);
	int a = 12;
	char ch = 'p';
	double b = 12.345;
	CString str = _T("大江東去浪淘盡, 千古風流人物");
	//儲存資料
	ar << a << ch << b << str;
}
//從檔案中讀取資料
void CArchiveView::OnReadfile()
{
	// TODO:  在此新增命令處理程式程式碼
	//構造CFile檔案物件
	CFile file(_T("demo.txt"), CFile::modeRead);
	//構造存檔物件
	CArchive ar(&file, CArchive::load);
	//定義變數,存放加載出來的資料
	int a;
	char ch;
	double b;
	CString str;
	//載入資料
	ar >> a >> ch >>b >> str;
	//格式化字串
	CString strResult;
	strResult.Format(_T("%d\n%c\n%lf\n%s"), a, ch, b, str);
	MessageBox(strResult);
}

CArchive物件處理自定義物件型別資料

CArchive物件不僅可以處理基礎型別,而且還能處理為序列化而設計的特殊的類的物件。可以序列化的類有以下特點

  • 必須為CObject派生類。直接或者間接的繼承CObject類;
  • 必須重寫CObject類的Serialize成員函式;
  • 使用DECLARE_SERIAL和IMPLEMENT_SERIAL巨集;
  • 必須有一個預設建構函式。

在Serialize成員函式中完成儲存和載入的功能。

DECLARE_SERIAL( class_name ) 引數為當前類名。
IMPLEMENT_SERIAL( class_name, base_class_name, wSchema ) 
  • 第一個引數為當前類名
  • 第二個引數為父類類名
  • 第三個引數為該類的特定整型標識,該標識將用來解序(重新例項化),最小為0。

示例:

DrawBase.h
//////////////////////////////////////////////////////
class CDrawBase : public CObject //繼承自CObject
{
public:
    DECLARE_SERIAL(CDrawBase)    //第一個巨集的位置,引數為當前類名
    CDrawBase();					//必須有一個預設建構函式
    virtual void onDraw(CDC* pdc);
    virtual ~CDrawBase();
public:
    UINT m_PenStyle;
    int m_PenWidth;
    int m_BkMode;
    int m_BrushStyle;
    int m_issx;
    int m_isyy;
    COLORREF m_PenColor;
    COLORREF m_BackgroundColor;
    COLORREF m_BrushColor;
    CPoint m_ptBegin;
    CPoint m_ptEnd;
public:
    void Serialize(CArchive& ar);		//重寫了Serialize成員函式
};
//////////////////////////////////////////////////////
DrawBase.cpp
//////////////////////////////////////////////////////
//第二個巨集的位置,第一個引數為當前類名,第二個引數為父類類名,
//第三個引數為該類的特定整型標識,該標識將用來解序(重新例項化),
//最小為0
IMPLEMENT_SERIAL(CDrawBase, CObject, 1)
void CDrawBase::Serialize(CArchive& ar)
{
    CObject::Serialize(ar);
    if(ar.IsStoring())		//儲存,載入為ar.IsLoading()
    {
        ar <<m_PenColor<<m_PenStyle<<m_PenWidth
<<m_BrushColor<<m_BrushStyle<<m_issx<<m_isyy;
    }
    else 	//載入
    {
    		ar >>m_PenColor>>m_PenStyle>>m_PenWidth>>
m_BrushColor>>m_BrushStyle>>m_issx>>m_isyy;
    }
}

總結

過載提取(>>)和插入(<<)是方便的歸檔程式設計介面。它支援主要型別和CObject派生類。
CArchive還支援使用MFC Windows套接字類CSocket和CSocketFile程式設計。IsBufferEmpty成員函式也支援這種使用。一些集合類也支援序列化,CObArray,Vector,CPtrArray。
在MFC文件-檢視結構中,Doc類是被系統設定好支援序列化的類,在Doc類中重寫Serialize成員函式。在函式中對你要儲存的物件序列化。完成之後,點選選單欄上的儲存和開啟就可以實現序列化了。

上一篇:MFC介面程式設計基礎(16):文件、檢視、框架 下一篇:MFC介面程式設計基礎(18):文件檢視結構應用程式例子(Ex_DocView)