青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

MyMSDN

MyMSDN記錄開發(fā)新知道

用文檔序列化來保存打開文件[理論聯(lián)系實(shí)際]

文檔與序列化

一、文檔的基本特征

文檔類文件是從CDocument繼承而來的。

The CDocument class provides the basic functionality for user-defined document classes. A document represents the unit of data that the user typically opens with the File Open command and saves with the File Save command.

翻譯:文檔類提供用戶自定義文檔類的基本功能。一個(gè)文檔的打開命令和保存命令是數(shù)據(jù)單元特征。

CDocument supports standard operations such as creating a document, loading it, and saving it. The framework manipulates documents using the interface defined by CDocument.

翻譯:文檔類支持標(biāo)準(zhǔn)操作有:創(chuàng)建文檔,載入文檔,和保存??蚣芙缑媸褂糜晌臋n類定義的界面。

An application can support more than one type of document; for example, an application might support both spreadsheets and text documents. Each type of document has an associated document template; the document template specifies what resources (for example, menu, icon, or accelerator table) are used for that type of document. Each document contains a pointer to its associated CDocTemplate object.

翻譯:一個(gè)應(yīng)用程序可以支持多于一種類型的文檔;例如,一個(gè)應(yīng)用程序可能同時(shí)支持電子表格和普通文本文檔。每一種類型的文檔有一種關(guān)聯(lián)文檔模板;文檔模板指定了(例如,菜單,圖標(biāo),或者加速表格)使用這些類型的文檔。每個(gè)文檔包含一個(gè)指針指向關(guān)聯(lián)的模板對象。

Users interact with a document through the CView object(s) associated with it. A view renders an image of the document in a frame window and interprets user input as operations on the document. A document can have multiple views associated with it. When the user opens a window on a document, the framework creates a view and attaches it to the document. The document template specifies what type of view and frame window are used to display each type of document.

翻譯:用戶將一個(gè)文檔和一個(gè)視類對象想關(guān)聯(lián)起來。一個(gè)視類扮演一個(gè)嵌入在文檔框架內(nèi)的圖像,在文檔內(nèi)解釋用戶的輸入操作。一個(gè)文檔可以有多個(gè)視類與其關(guān)聯(lián)。當(dāng)用戶在一個(gè)文檔上打開一個(gè)窗體,框架創(chuàng)造一個(gè)視圖,把它放在文檔上。文檔模板指定適合于用戶文檔類型的相同類的視圖和框架窗口用來顯示用戶打開的文件。

Documents are part of the framework's standard command routing and consequently receive commands from standard user-interface components (such as the File Save menu item). A document receives commands forwarded by the active view. If the document doesn't handle a given command, it forwards the command to the document template that manages it.

翻譯:文檔是一個(gè)框架標(biāo)準(zhǔn)命令路由,因此從標(biāo)準(zhǔn)用戶界面組件(如文件保存菜單項(xiàng))接受命令。一個(gè)文檔由其活動(dòng)視圖迅速接受命令。如果該文檔沒有沒有響應(yīng)給出的命令,那么該命令將交由文檔模板來管理。

When a document's data is modified, each of its views must reflect those modifications. CDocument provides the UpdateAllViews member function for you to notify the views of such changes, so the views can repaint themselves as necessary. The framework also prompts the user to save a modified file before closing it.

翻譯:當(dāng)一個(gè)文檔數(shù)據(jù)發(fā)生改變,每一個(gè)它的視圖將隨即發(fā)生改變。文檔類提供更新所有視圖成員函數(shù)來通報(bào)每一個(gè)視圖的改變,因此視圖可以在必要的時(shí)候被重繪。框架也在關(guān)閉前迅速保存改動(dòng)文件。

To implement documents in a typical application, you must do the following:

l???????? Derive a class from CDocument for each type of document.

l???????? Add member variables to store each document's data.

l???????? Implement member functions for reading and modifying the document's data. The document's views are the most important users of these member functions.

l???????? Override the CObject::Serialize member function in your document class to write and read the document's data to and from disk.

翻譯:在一個(gè)典型類型的應(yīng)用程序中實(shí)現(xiàn)一個(gè)文檔,你必須按以下步驟:

l???????? 為每一種類型的文檔從 CDocument 派生一個(gè)類

l???????? 增加成員函數(shù)來存儲每一個(gè)文檔的數(shù)據(jù)

l???????? 為讀寫文檔數(shù)據(jù)實(shí)現(xiàn)成員函數(shù)。文檔視圖類是這個(gè)成員函數(shù)最重要的使用者。

l???????? 在你的文檔類重載 CObject::Serialize 成員函數(shù),來將文檔數(shù)據(jù)從磁盤讀寫。

序列化:

本文解釋 Microsoft 基礎(chǔ)類庫 (MFC) 中提供的序列化機(jī)制,該機(jī)制使對象可以在程序運(yùn)行之間保持。

序列化是指將對象寫入永久性存儲媒體(如磁盤文件)或從其中讀取對象的進(jìn)程。 MFC CObject 類中的序列化提供內(nèi)置支持。因此,所有從 CObject 派生的類都可利用 CObject 的序列化協(xié)議。

序列化的基本思想是對象應(yīng)能將其當(dāng)前狀態(tài)(通常由該對象的成員變量指示)寫入永久性存儲中。以后,通過從存儲中讀取對象狀態(tài)或反序列化對象狀態(tài),可以重新創(chuàng)建該對象。序列化處理序列化對象時(shí)使用的對象指針和對象循環(huán)引用的所有詳細(xì)資料。關(guān)鍵之處在于對象本身負(fù)責(zé)讀寫其自身狀態(tài)。因此,對于可序列化的類,必須實(shí)現(xiàn)基本的序列化操作。正如 序列化 文章組中所顯示的那樣,很容易將該功能添加到類中。

MFC CArchive 類的對象用作將被序列化的對象和存儲媒體之間的中介物。該對象始終與 CFile 對象相關(guān)聯(lián),它從 CFile 對象獲得序列化所需的信息,包括文件名和請求的操作是讀取還是寫入。執(zhí)行序列化操作的對象可在不考慮存儲媒體本質(zhì)的情況下使用 CArchive 對象。

CArchive 對象使用重載輸出運(yùn)算符 (<<) 和輸入運(yùn)算符 (>>) 來執(zhí)行讀寫操作。有關(guān)更多信息,請參見 序列化:序列化對象 文章中的 通過存檔存儲和加載 CObjects

注意 ??? 請不要將 CArchive 類與通用 iostream 類混淆, iostream 類只用于格式化的文本。而 CArchive 類則用于二進(jìn)制格式的序列化對象。

如果愿意,可以不使用 MFC 序列化而為永久性數(shù)據(jù)存儲創(chuàng)建自己的機(jī)制。您將需要在用戶的命令處重寫啟動(dòng)序列化的類成員函數(shù)。請參見 ID_FILE_OPEN 、 ID_FILE_SAVE ID_FILE_SAVE_AS 標(biāo)準(zhǔn)命令的 技術(shù)說明 22 中的討論。

下列文章介紹了序列化所需的兩個(gè)主要任務(wù):

l???????? 序列化:創(chuàng)建可序列化的類

l???????? 序列化:序列化對象

序列化:序列化與數(shù)據(jù)庫輸入 /輸出的對比 一文描述了序列化在數(shù)據(jù)庫應(yīng)用程序中何時(shí)是適當(dāng)?shù)妮斎?/span> / 輸出技術(shù)。

通過存檔存儲和加載 CObjects

通過存檔存儲及加載 CObject 需要額外注意。在某些情況下,應(yīng)調(diào)用對象的 Serialize 函數(shù),其中, CArchive 對象是 Serialize 調(diào)用的參數(shù),與使用 CArchive “<<” “>>” 運(yùn)算符不同。要牢記的重要事實(shí)是: CArchive “>>” 運(yùn)算符基于由存檔先前寫到文件的 CRuntimeClass 信息構(gòu)造內(nèi)存中的 CObject

因此,是使用 CArchive “<<” “>>” 運(yùn)算符還是調(diào)用 Serialize ,取決于是否需要加載存檔基于先前存儲的 CRuntimeClass 信息動(dòng)態(tài)地重新構(gòu)造對象。在下列情況下使用 Serialize 函數(shù):

l???????? 反序列化對象時(shí),預(yù)先知道對象的確切的類。

l???????? 反序列化對象時(shí),已為其分配了內(nèi)存。

警告 ??? 如果使用 Serialize 函數(shù)加載對象,也必須使用 Serialize 函數(shù)存儲對象。不要使用 CArchive “<<” 運(yùn)算符先存儲,然后使用 Serialize 函數(shù)進(jìn)行加載;或使用 Serialize 函數(shù)存儲,然后使用 CArchive “>>” 運(yùn)算符進(jìn)行加載。

以下示例闡釋了這些情況:

class CMyObject : public CObject

{

// ...Member functions

?? public:

?? CMyObject() { }

?? virtual void Serialize( CArchive& ar ) { }

?

// Implementation

?? protected:

?? DECLARE_SERIAL( CMyObject )

};

?

?

class COtherObject : public CObject

{

?? // ...Member functions

?? public:

?? COtherObject() { }

?? virtual void Serialize( CArchive& ar ) { }

?

// Implementation

protected:

?? DECLARE_SERIAL( COtherObject )

};

?

?

class CCompoundObject : public CObject

{

?? // ...Member functions

?? public:

?? CCompoundObject();

?? virtual void Serialize( CArchive& ar );

?

// Implementation

protected:

?? CMyObject m_myob;??? // Embedded object

?? COtherObject* m_pOther;??? // Object allocated in constructor

?? CObject* m_pObDyn;??? // Dynamically allocated object

?? //..Other member data and implementation

?

?? DECLARE_SERIAL( CCompoundObject )

};

?

IMPLEMENT_SERIAL(CMyObject,CObject,1)

IMPLEMENT_SERIAL(COtherObject,CObject,1)

IMPLEMENT_SERIAL(CCompoundObject,CObject,1)

?

?

CCompoundObject::CCompoundObject()

{

?? m_pOther = new COtherObject; // Exact type known and object already

??????????? //allocated.

?? m_pObDyn = NULL;??? // Will be allocated in another member function

??????????? // if needed, could be a derived class object.

}

?

void CCompoundObject::Serialize( CArchive& ar )

{

?? CObject::Serialize( ar );??? // Always call base class Serialize.

?? m_myob.Serialize( ar );??? // Call Serialize on embedded member.

?? m_pOther->Serialize( ar );??? // Call Serialize on objects of known exact type.

?

?? // Serialize dynamic members and other raw data

?? if ( ar.IsStoring() )

?? {

????? ar << m_pObDyn;

????? // Store other members

?? }

?? else

?? {

????? ar >> m_pObDyn; // Polymorphic reconstruction of persistent

??????????? // object

??????????? //load other members

?? }

}

總之,如果可序列化的類將嵌入的 CObject 定義為成員,則不應(yīng)使用該對象的 CArchive “<<” “>>” 運(yùn)算符,而應(yīng)調(diào)用 Serialize 函數(shù)。同時(shí),如果可序列化的類將指向 CObject (或從 CObject 派生的對象)的指針定義為成員,但在自己的構(gòu)造函數(shù)中將其構(gòu)造為其他對象,則也應(yīng)調(diào)用 Serialize

序列化:創(chuàng)建可序列化的類

ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/vccore/html/_core_serialization.3a_.making_a_serializable_class.htm

使類可序列化需要五個(gè)主要步驟。下面列出了這些步驟并在以后章節(jié)內(nèi)進(jìn)行了解釋:

  1. CObject 派生類 (或從 CObject 派生的某個(gè)類中派生)。
  2. 重寫 Serialize 成員函數(shù)
  3. 使用 DECLARE_SERIAL (在類聲明中)。
  4. 定義不帶參數(shù)的構(gòu)造函數(shù)
  5. 為類 在實(shí)現(xiàn)文件中使用 IMPLEMENT_SERIAL 。

如果直接調(diào)用 Serialize而不是通過 CArchive“>>”“<<”運(yùn)算符調(diào)用,則序列化不需要最后三個(gè)步驟。

CObject 派生類

CObject 類中定義了基本的序列化協(xié)議和功能。正如在 CPerson 類的下列聲明中所示,通過從 CObject 中(或從 CObject 的派生類中)派生類,可獲得對 CObject 的序列化協(xié)議及功能的訪問權(quán)限。

?

重寫 Serialize 成員函數(shù)

?

CObject 類中定義的 Serialize 成員函數(shù)實(shí)際上負(fù)責(zé)對捕獲對象的當(dāng)前狀態(tài)所必需的數(shù)據(jù)進(jìn)行序列化。 Serialize 函數(shù)具有 CArchive 參數(shù),該函數(shù)使用其來讀寫對象數(shù)據(jù)。 CArchive 對象具有成員函數(shù) IsStoring ,該成員函數(shù)指示 Serialize 正在存儲(即正在寫入數(shù)據(jù))還是正在加載(即正在讀取數(shù)據(jù))。用 IsStoring 的結(jié)果作為參考,使用輸出運(yùn)算符 (<<) 將對象數(shù)據(jù)插入到 CArchive 對象中或使用輸入運(yùn)算符 (>>) 提取數(shù)據(jù)。

假定一個(gè)類是從 CObject 派生的并具有兩個(gè)新成員變量,分別為 CString WORD 類型。下列類聲明段顯示了新成員變量和重寫的 Serialize 成員函數(shù)的聲明:

class CPerson : public CObject

{

public:

??? DECLARE_SERIAL( CPerson )

??? // empty constructor is necessary

??? CPerson(){};

?

??? CString m_name;

??? WORD?? m_number;

?

??? void Serialize( CArchive& archive );

???

??? // rest of class declaration

};

?

重寫 Serialize 成員函數(shù)

  1. 調(diào)用 Serialize 的基類版本以確保序列化對象的繼承部分。
  2. 插入或提取您的類所特定的成員變量。

輸出運(yùn)算符及輸入運(yùn)算符與存檔類交互作用以讀寫數(shù)據(jù)。下面的示例顯示了如何實(shí)現(xiàn)以上聲明的 CPerson類的 Serialize

				
						
void ?CPerson::Serialize(?CArchive & ?archive?)
{
????
// ?call?base?class?function?first
????
// ?base?class?is?CObject?in?this?case
????CObject::Serialize(?archive?);

????
// ?now?do?the?stuff?for?our?specific?class
???? if (?archive.IsStoring()?)
????????archive?
<< ?m_name? << ?m_number;
????
else
????????archive?
>> ?m_name? >> ?m_number;
}

也可使用 CArchive::ReadCArchive::Write成員函數(shù)來讀寫大量未鍵入的數(shù)據(jù)。

使用 DECLARE_SERIAL

在支持序列化的類的聲明中需要 DECLARE_SERIAL宏,如下所示:

				
class ?CPerson?:? public ?CObject
{
????DECLARE_SERIAL(?CPerson?)
????
// ?rest?of?declaration?follows
}
;
定義不帶參數(shù)的構(gòu)造函數(shù)

反序列化對象(從磁盤上加載)后,MFC 重新創(chuàng)建這些對象時(shí),需要一個(gè)默認(rèn)的構(gòu)造函數(shù)。反序列化進(jìn)程將用重新創(chuàng)建對象所需的值填充所有成員變量。

可將該構(gòu)造函數(shù)聲明為公共的、受保護(hù)的或私有的。如果使該構(gòu)造函數(shù)成為受保護(hù)的或私有的,請確保它將僅由序列化函數(shù)使用。該構(gòu)造函數(shù)必須使對象處于這樣一種狀態(tài):必要時(shí),可允許將其安全刪除。

注意 ??? 如果忘記在使用 DECLARE_SERIAL IMPLEMENT_SERIAL 宏的類中定義不帶參數(shù)的構(gòu)造函數(shù),將在使用 IMPLEMENT_SERIAL 宏的行上得到 沒有可用的默認(rèn)構(gòu)造函數(shù) 編譯器警告。

在實(shí)現(xiàn)文件中使用 IMPLEMENT_SERIAL

IMPLEMENT_SERIAL 宏用于定義從 CObject中派生可序列化類時(shí)所需的各種函數(shù)。在類的實(shí)現(xiàn)文件 (.CPP) 中使用這個(gè)宏。該宏的前兩個(gè)參數(shù)是類名和直接基類的名稱。

該宏的第三個(gè)參數(shù)是架構(gòu)編號。架構(gòu)編號實(shí)質(zhì)上是類對象的版本號。架構(gòu)編號使用大于或等于零的整數(shù)。(請不要將該架構(gòu)編號與數(shù)據(jù)庫術(shù)語混淆。)

MFC 序列化代碼在將對象讀取到內(nèi)存時(shí)檢查該架構(gòu)編號。如果磁盤上對象的架構(gòu)編號與內(nèi)存中類的架構(gòu)編號不匹配,庫將引發(fā) CArchiveException,防止程序讀取對象的不正確版本。

如果要使 Serialize成員函數(shù)能夠讀取多個(gè)版本(即,讀取用應(yīng)用程序的不同版本寫入的文件),可將 VERSIONABLE_SCHEMA值作為 IMPLEMENT_SERIAL宏的參數(shù)。有關(guān)用法信息和示例,請參見 CArchive類的 GetObjectSchema成員函數(shù)。

以下示例顯示了如何將 IMPLEMENT_SERIAL用于從 CObject派生的 CPerson類。

				
						IMPLEMENT_SERIAL( CPerson, CObject, 1 )
				
		

正如序列化:序列化對象文章中所討論的,一旦具有可序列化的類,就可以序列化類的對象。

序列化 :序列化對象

序列化:創(chuàng)建可序列化的類 一文說明如何使類可序列化。一旦具有可序列化的類,就可以通過 CArchive對象將該類的對象序列化到文件和從文件序列化該類的對象。本文將解釋:

可使框架創(chuàng)建可序列化文檔的存檔或自己顯式創(chuàng)建 CArchive對象。通過使用 CArchive“<<”“>>”運(yùn)算符或在某些情況下通過調(diào)用 CObject派生類的 Serialize 函數(shù),可在文件和可序列化對象間傳輸數(shù)據(jù)。

什么是Archive對象?

CArchive 對象提供了一個(gè)類型安全緩沖機(jī)制,用于將可序列化對象寫入 CFile對象或從中讀取可序列化對象。通常,CFile對象表示磁盤文件;但是,它也可以是表示剪貼板的內(nèi)存文件(CSharedFile對象)。

給定的 CArchive對象要么存儲數(shù)據(jù)(即寫入數(shù)據(jù)或?qū)?shù)據(jù)序列化),要么加載數(shù)據(jù)(即讀取數(shù)據(jù)或?qū)?shù)據(jù)反序列化),但決不能同時(shí)進(jìn)行。CArchive對象的壽命只限于將對象寫入文件或從文件讀取對象的一次傳遞。因此,需要兩個(gè)連續(xù)創(chuàng)建的 CArchive對象將數(shù)據(jù)序列化到文件,然后從文件反序列化數(shù)據(jù)。

當(dāng)存檔將對象存儲到文件時(shí),存檔將 CRuntimeClass名稱附加到這些對象。然后,當(dāng)另一個(gè)存檔將對象從文件加載到內(nèi)存時(shí),將基于這些對象的 CRuntimeClass動(dòng)態(tài)地重新構(gòu)造 CObject派生的對象。通過存儲存檔將給定對象寫入文件時(shí),該對象可能被引用多次。然而,加載存檔將僅對該對象重新構(gòu)造一次。有關(guān)存檔如何將 CRuntimeClass信息附加到對象以及重新構(gòu)造對象(考慮可能的多次引用)的詳細(xì)信息,請參見技術(shù)說明 2 。

將數(shù)據(jù)序列化到存檔時(shí),存檔積累數(shù)據(jù),直到其緩沖區(qū)被填滿為止。然后,存檔將其緩沖區(qū)寫入 CArchive對象指向的 CFile對象。同樣,當(dāng)您從存檔中讀取數(shù)據(jù)時(shí),存檔會將數(shù)據(jù)從文件讀取到它的緩沖區(qū),然后從緩沖區(qū)讀取到反序列化的對象。這種緩沖減少了物理讀取硬盤的次數(shù),從而提高了應(yīng)用程序的性能。

創(chuàng)建 CArchive 對象有兩種方法:

l???????? 通過框架隱式創(chuàng)建 CArchive 對象

l???????? 顯式創(chuàng)建 CArchive 對象

通過框架隱式創(chuàng)建 CArchive 對象

最普通且最容易的方法是使框架代表“文件”菜單上的“保存”、“另存為”和“打開”命令為文檔創(chuàng)建 CArchive 對象。

以下是應(yīng)用程序的用戶從“文件”菜單上發(fā)出“另存為”命令時(shí),框架所執(zhí)行的操作:

顯示“另存為”對話框并從用戶獲取文件名。

打開用戶命名的文件作為 CFile 對象。

創(chuàng)建指向該 CFile 對象的 CArchive 對象。在創(chuàng)建 CArchive 對象時(shí),框架將模式設(shè)置為“存儲”(即寫入或序列化),而不是“加載”(即讀取或反序列化)。

調(diào)用在 CDocument 派生類中定義的 Serialize 函數(shù),將 CArchive 對象的引用傳遞給該函數(shù)。

然后,文檔的 Serialize 函數(shù)將數(shù)據(jù)寫入 CArchive 對象(剛作了解釋)。從 Serialize 函數(shù)返回時(shí),框架先銷毀 CArchive 對象,再銷毀 CFile 對象。

因此,如果讓框架為文檔創(chuàng)建 CArchive 對象,您所要做的一切是實(shí)現(xiàn)寫入存檔和從存檔中讀取的文檔的 Serialize 函數(shù)。您還必須為文檔的 Serialize 函數(shù)直接或間接依次序列化的任何 CObject 派生對象實(shí)現(xiàn) Serialize 。

顯式創(chuàng)建 CArchive 對象

除了通過框架將文檔序列化之外,在其他場合也可能需要 CArchive 對象。例如,可能要序列化到達(dá)或來自剪貼板的數(shù)據(jù),由 CSharedFile 對象表示。或者,可能要使用用戶界面來保存與框架提供的文件不同的文件。在這種情況下,可以顯式創(chuàng)建 CArchive 對象。使用下列過程,用與框架采用的相同方式來執(zhí)行此操作。

顯式創(chuàng)建 CArchive 對象

構(gòu)造 CFile 對象或從 CFile 導(dǎo)出的對象。

按照下面示例所示,將 CFile 對象傳遞到 CArchive 的構(gòu)造函數(shù):

CFile theFile;

theFile.Open(..., CFile::modeWrite);

CArchive archive(&theFile, CArchive::store);

CArchive 構(gòu)造函數(shù)的第二個(gè)參數(shù)是指定存檔將用于向文件中存儲數(shù)據(jù)還是用于從文件中加載數(shù)據(jù)的枚舉值。對象的 Serialize 函數(shù)通過調(diào)用存檔對象的 IsStoring 函數(shù)來檢查該狀態(tài)。

當(dāng)完成向 CArchive 對象存儲數(shù)據(jù)或從該對象中加載數(shù)據(jù)時(shí),關(guān)閉該對象。雖然 CArchive 對象(和 CFile 對象)會自動(dòng)關(guān)閉存檔(和文件),好的做法是顯式執(zhí)行,因?yàn)檫@使從錯(cuò)誤恢復(fù)更為容易。有關(guān)錯(cuò)誤處理的更多信息,請參見異常:捕捉和刪除異常一文。

關(guān)閉 CArchive 對象

以下示例闡釋了如何關(guān)閉 CArchive 對象:

archive.Close();

theFile.Close();

?

使用 CArchive 對象的“ << ”和“ >> ”操作符

CArchive 提供“ << ”和“ >> ”運(yùn)算符,用于向文件中寫入簡單的數(shù)據(jù)類型和 CObjects 以及從文件中讀取它們。

通過存檔將對象存儲在文件中

以下示例顯示了如何通過存檔將對象存儲在文件中:

CArchive ar(&theFile, CArchive::store);

WORD wEmployeeID;

...

ar << wEmployeeID;

從先前存儲在文件中的值加載對象

以下示例顯示了如何從先前存儲在文件中的值加載對象:

CArchive ar(&theFile, CArchive::load);

WORD wEmployeeID;

...

ar >> wEmployeeID;

通常,通過 CObject 派生類的 Serialize 函數(shù)中的存檔將數(shù)據(jù)存儲到文件中或從文件中加載數(shù)據(jù),必須已用 DECLARE_SERIALIZE 宏來聲明這些函數(shù)。將 CArchive 對象的引用傳遞到 Serialize 函數(shù)。調(diào)用 CArchive 對象的 IsLoading 函數(shù)以確定是否已調(diào)用 Serialize 函數(shù)來從文件中加載數(shù)據(jù)或?qū)?shù)據(jù)存儲到文件中。

可序列化的 CObject 派生類的 Serialize 函數(shù)通常具有以下形式:

void CPerson::Serialize(CArchive& ar)

{

??? CObject::Serialize(ar);

??? if (ar.IsStoring())

??? {

??????? // TODO:? add storing code here

??? }

??? else

??? {

??? // TODO:? add loading code here

??? }

}

上面的代碼模板與 AppWizard 為該文檔(從 CDocument 派生的類)的 Serialize 函數(shù)所創(chuàng)建的代碼模板完全相同。由于存儲代碼和加載代碼總是并行,該代碼模板有助于寫的代碼更容易復(fù)查,如下例中所示:

void CPerson:Serialize(CArchive& ar)

{

??? if (ar.IsStoring())

??? {

??????? ar << m_strName;

??????? ar << m_wAge;

??? }

??? else

??? {

??????? ar >> m_strName;

??????? ar >> m_wAge;

??? }

}

庫將 CArchive 的“ << ”和“ >> ”運(yùn)算符定義為第一操作數(shù),將下列數(shù)據(jù)類型和類類型定義為第二操作數(shù):

CObject*

SIZE CSize

float

WORD

CString

POINT CPoint

DWORD

BYTE

RECT CRect

double

LONG

CTime CTimeSpan

int

COleCurrency

COleVariant

COleDateTime

COleDateTimeSpan

?

?

注意 ?? 通過存檔存儲及加載 CObjects 需要額外注意。有關(guān)更多信息,請參見通過存檔存儲和加載 CObjects

CArchive 的“ << ”和“ >> ”運(yùn)算符總是返回 CArchive 對象的引用,該引用為第一操作數(shù)。這使您可以鏈接運(yùn)算符,如下所示:

BYTE bSomeByte;

WORD wSomeWord;

DWORD wSomeDoubleWord;

...

ar << bSomeByte << wSomeWord << wSomeDoubleWord;

?

?

通過存檔存儲及加載 CObject (見前)

下面用一個(gè)示例來解釋這個(gè)問題。

目標(biāo):一個(gè)畫圖程序,通過保存打開按鈕存取圖片。方法:保存圖片繪制信息。

按步驟:

l???????? 創(chuàng)建可序列化的類 ->Graph.cpp+Graph.h

l???????? View 類中添加對控件的響應(yīng),實(shí)現(xiàn)畫圖功能,每次鼠標(biāo)彈起的時(shí)候保存繪圖信息

l???????? 保存文件(通過 Doc Serialize 來保存數(shù)據(jù))

l???????? 打開文件(通過 Doc Serialize 來讀取數(shù)據(jù),并將其重繪)

View 類中定義 CObArray m_obArray;

下面按這個(gè)思路來完成:(在 C Graph 子類中完成重繪的畫圖功能)

Graph.cpp

#include "StdAfx.h"

#include ".\graph.h"

IMPLEMENT_SERIAL(CGraph, CObject, 1 )

CGraph::CGraph(void)

: m_ptOrigin(0)

, m_ptEnd(0)

, m_nDrawType(0)

{

}

CGraph::CGraph(CPoint m_ptOrigin,CPoint m_ptEnd,UINT m_nDrawType)

{

???? this->m_ptOrigin=m_ptOrigin;

???? this->m_ptEnd=m_ptEnd;

???? this->m_nDrawType=m_nDrawType;

}

CGraph::~CGraph(void)

{

}

void CGraph::Serialize( CArchive& ar )

{

???? // 繼承基類的CObject

??? CObject::Serialize( ar );

??? if( ar.IsStoring() )

???? {

??????? ar << m_ptOrigin << m_ptEnd << m_nDrawType ;

???? }

???? else

???? {

???????? ar >> m_ptOrigin >> m_ptEnd >> m_nDrawType ;

???? }

}

void CGraph::Draw(CDC* pDC)

{

???? CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

???? CBrush *pOldBrush=pDC->SelectObject(pBrush);

???? switch(m_nDrawType)

???? {

???? case 1:

???????? pDC->SetPixel(m_ptEnd,RGB(0,0,0));

???????? break;

???? case 2:

???????? pDC->MoveTo(m_ptOrigin);

???????? pDC->LineTo(m_ptEnd);

???????? break;

???? case 3:

???????? pDC->Rectangle(CRect(m_ptOrigin,m_ptEnd));

???????? break;

???? case 4:

???????? pDC->Ellipse(CRect(m_ptOrigin,m_ptEnd));

???????? break;

???? }

???? pDC->SelectObject(pOldBrush);

}

Graph..h

#pragma once

#include "atltypes.h"

?

class CGraph : publicCObject

{

public :

???? DECLARE_SERIAL( CGraph )

???? CGraph(void);

???? CGraph::CGraph(CPoint m_ptOrigin,CPoint m_ptEnd,UINT m_nDrawType);

???? void Serialize( CArchive& ar );

???? ~CGraph(void);

???? CPoint m_ptOrigin;

???? CPoint m_ptEnd;

???? UINT m_nDrawType;

???? void Draw(CDC* pDC);

};

View 類中添加畫圖功能

void CGraphicSerialView::OnDot()

{

???? // TODO: 在此添加命令處理程序代碼

???? m_nDrawType=1;

}

?

void CGraphicSerialView::OnLine()

{

???? // TODO: 在此添加命令處理程序代碼

???? m_nDrawType=2;

}

?

void CGraphicSerialView::OnRectangle()

{

???? // TODO: 在此添加命令處理程序代碼

???? m_nDrawType=3;

}

?

void CGraphicSerialView::OnEllipse()

{

???? // TODO: 在此添加命令處理程序代碼

???? m_nDrawType=4;

}

?

void CGraphicSerialView::OnLButtonDown(UINT nFlags, CPoint point)

{

???? // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值

???? m_ptOrigin = point;

???? CView::OnLButtonDown(nFlags, point);

}

?

void CGraphicSerialView::OnLButtonUp(UINT nFlags, CPoint point)

{

???? // TODO: 在此添加消息處理程序代碼和/或調(diào)用默認(rèn)值

???? CClientDC dc(this);

???? CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));???? // 選擇一個(gè)透明畫刷

???? dc.SelectObject(pBrush);

?

???? switch(m_nDrawType)

???? {

???? case 1:

???????? dc.SetPixel(point,RGB(0,0,0));

???????? break;

???? case 2:

???????? dc.MoveTo(m_ptOrigin);

???????? dc.LineTo(point);

???????? break;

???? case 3:

???????? dc.Rectangle(m_ptOrigin.x,m_ptOrigin.y,point.x,point.y);

???????? break;

???? case 4:

???????? dc.Ellipse(CRect(m_ptOrigin,point));

???????? break;

???? default:

???????? break;

???? }

???? // 將圖形信息保存起來

???? CGraph *pGraph=new CGraph( m_ptOrigin , point , m_nDrawType );?? // 創(chuàng)建一個(gè)pGraph指針指向一個(gè)存儲圖形信息的“圖形”

???? m_obArray.Add(pGraph);// 將一群這樣的pGraph組織在一起放進(jìn)m_obArray

???? CView::OnLButtonUp(nFlags, point);

}

但是要保存和讀取文件需要用到 Serialize

因此轉(zhuǎn)到 Doc

void CGraphicSerialDoc::Serialize(CArchive& ar)

{

???? POSITION pos=GetFirstViewPosition();// 獲得第一個(gè)視類對象在對象列表中的位置

???? CGraphicSerialView *pView=(CGraphicSerialView*)GetNextView(pos);// 找到當(dāng)前視類對象的指針,由于這是單文檔,因此只有一個(gè)視類對象

???? if (ar.IsStoring())

???? {

???????? // TODO: 在此添加存儲代碼

???????? int nCount=pView->m_obArray.GetSize();

???????? ar<<nCount;?? // 為了在讀取文件的時(shí)候能夠知道元素個(gè)數(shù),因此在保存的時(shí)候把個(gè)數(shù)也存進(jìn)去

???????? for(int i=0;i<nCount;i++)

???????? {

????????????? ar<<pView->m_obArray.GetAt(i);

???????? }

???? }

???? else

???? {

???????? // TODO: 在此添加加載代碼

???????? int nCount;

???????? ar>>nCount;

???????? CGraph *pGraph;

???????? for(int i=0;i<nCount;i++)

???????? {

????????????? ar>>pGraph;

????????????? pView->m_obArray.Add(pGraph);

???????? }

???? }

}

但是讀取數(shù)據(jù)的時(shí)候還需要重繪圖像:轉(zhuǎn)回View類,因?yàn)樵?span lang="EN-US">View類加載的時(shí)候會自動(dòng)調(diào)用OnDraw(),OnDraw()中添加如下語句。

???? int nCount;

???? nCount=m_obArray.GetSize();

???? for(int i=0;i<nCount;i++)

???? {

???????? ((CGraph*)m_obArray.GetAt(i))->Draw(pDC);

???? }

基本上完成了通過serialize保存和打開文件。

serialize的好處:通過緩存來保存,當(dāng)緩存區(qū)滿了才進(jìn)行一次讀/寫,因此提高了應(yīng)用程序的效率

?

另外 , Archive 對象是支持序列化的,因此在讀寫數(shù)據(jù)的時(shí)候即可以按以上方法在 Doc 類的 Serialize 來保存和打開數(shù)據(jù)。

因此修改 Doc 中的 Serialize

void CGraphicSerialDoc::Serialize(CArchive& ar)

{

???? POSITION pos=GetFirstViewPosition();// 獲得第一個(gè)視類對象在對象列表中的位置

???? CGraphicSerialView *pView=(CGraphicSerialView*)GetNextView(pos);// 找到當(dāng)前視類對象的指針,由于這是單文檔,因此只有一個(gè)視類對象

???? if (ar.IsStoring())

???? {

???????? // TODO: 在此添加存儲代碼

???? }

???? else

???? {

???????? // TODO: 在此添加加載代碼

???? }

???? pView->m_obArray.Serialize(ar);? // 將這個(gè)數(shù)據(jù)傳遞給

}

其中CObArray類對象讀取數(shù)據(jù)的方法:(以下是MFC源代碼,無須用戶添加)

void CObArray::Serialize(CArchive& ar)

{

???? ASSERT_VALID(this);

?

???? CObject::Serialize(ar);

?

???? if (ar.IsStoring())

???? {

???????? ar.WriteCount(m_nSize);

???????? for (INT_PTR i = 0; i < m_nSize; i++)

????????????? ar << m_pData[i];

???? }

???? else

???? {

???????? DWORD_PTR nOldSize = ar.ReadCount();

???????? SetSize(nOldSize);

???????? for (INT_PTR i = 0; i < m_nSize; i++)

????????????? ar >> m_pData[i];

???? }

}

?

下面直接在 Doc 類中使用 CObArray 對象(取消之前定義在 View 類中的該類對象)

Doc 類中定義 CObArray m_obArray;

存圖形數(shù)據(jù)的代碼修改為:

???? CGraphicDoc *pDoc=GetDocument();// 通過視類提供的GetDocument()方法來獲得Doc類指針

???? pDoc->m_obArray.Add(pGraph);

修改其他位置的 m_obArray

void CGraphicSerialView::OnDraw(CDC* pDC)

{

???? ……

???? nCount=pDoc->m_obArray.GetSize();

???? for(int i=0;i<nCount;i++)

???? {

???? ???? ((CGraph*)pDoc->m_obArray.GetAt(i))->Draw(pDC);???//Doc類中定義m_obArray的情況

???? }

}

void CGraphicSerialDoc::Serialize(CArchive& ar)

{

……

???? m_obArray.Serialize(ar); ??? //Doc 類中定義m_obArray的情況

}

當(dāng)我們新建和打開文檔的時(shí)候,我們之前的文檔對象并沒有被銷毀(系統(tǒng)利用 OnNewDocument 方法所新建的對象)之前在堆上建立了文檔對象。此時(shí)應(yīng)刪除文檔對象。

在文檔類中重載函數(shù) void CGraphicSerialDoc::DeleteContents() 來刪除文檔對象,以避免內(nèi)存泄露。

void CGraphicSerialDoc::DeleteContents()

{

???? int nCount;

???? nCount=m_obArray.GetSize();

???? /*for(int i=0;i<nCount;i++)

???? {

???????? delete m_obArray.GetAt(i);

???????? //m_obArray.RemoveAt(i);

???? }

???? m_obArray.RemoveAll();*/

???? while(nCount--)

???? {

???????? delete m_obArray.GetAt(nCount);

???????? m_obArray.RemoveAt(nCount);

???? }

???? CDocument::DeleteContents();

}

下面是關(guān)于內(nèi)存泄露的在此的一段論述。(此文同時(shí)發(fā)布于)

http://m.shnenglu.com/mymsdn/archive/2006/08/16/11266.html

posted on 2006-08-16 23:19 volnet 閱讀(2445) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


特殊功能
 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美成ee人免费视频| 日韩视频一区二区在线观看| 亚洲人成亚洲人成在线观看| 亚洲欧美日韩国产一区| 狠狠干综合网| 好吊色欧美一区二区三区四区| 欧美乱大交xxxxx| 欧美xxxx在线观看| 欧美美女bb生活片| 欧美午夜宅男影院| 欧美gay视频激情| 欧美福利精品| 一本久道综合久久精品| 中文一区二区| 久久精品麻豆| 欧美a级理论片| 国产精品久久久久久久久久妞妞 | 欧美中文在线免费| 狠狠爱www人成狠狠爱综合网| 国内精品久久久久久久影视麻豆 | 国产亚洲观看| 在线观看精品一区| 一区二区三区欧美激情| 久久国产精品99精品国产| 久色成人在线| 日韩视频精品在线| 欧美一区二区三区喷汁尤物| 毛片av中文字幕一区二区| 欧美日韩国产精品自在自线| 国产综合香蕉五月婷在线| 日韩亚洲欧美高清| 老司机免费视频一区二区| 日韩特黄影片| 欧美国产视频在线观看| 国内精品免费午夜毛片| 亚洲午夜视频在线观看| 牛牛影视久久网| 久久久久.com| 在线亚洲欧美视频| 欧美日韩成人一区二区三区| 亚洲国产精品成人综合色在线婷婷| 亚洲欧美制服中文字幕| 日韩视频中文字幕| 欧美精品在线免费播放| 9色精品在线| 亚洲精品乱码久久久久| 欧美极品在线观看| 日韩一级大片在线| 亚洲伦伦在线| 国产精品一区二区三区免费观看| 亚洲天堂免费观看| 亚洲在线黄色| 亚洲第一区色| 一本一本大道香蕉久在线精品| 欧美精品一区二区蜜臀亚洲| 亚洲社区在线观看| 香蕉久久一区二区不卡无毒影院| 国产亚洲精品一区二555| 久久综合国产精品| 欧美freesex交免费视频| 9i看片成人免费高清| 午夜精品一区二区三区四区| 亚洲黄色在线| 亚洲专区在线视频| 亚洲黄色小视频| 性欧美暴力猛交69hd| 亚洲精品色图| 久久综合久久综合久久| 午夜亚洲一区| 欧美日韩一本到| 免费成人毛片| 狠狠色噜噜狠狠狠狠色吗综合| 91久久精品日日躁夜夜躁欧美| 一区二区三区久久网| 在线日韩日本国产亚洲| 午夜精品影院在线观看| 一本大道久久a久久综合婷婷| 久久精品视频一| 久久色中文字幕| 国一区二区在线观看| 午夜精品在线看| 久久精品国产精品 | 99热这里只有成人精品国产| 伊人成年综合电影网| 久久国产精品亚洲77777| 久久久激情视频| 黄色欧美日韩| 欧美~级网站不卡| 亚洲国产精品久久人人爱蜜臀| 在线观看成人小视频| 免费看亚洲片| 一本综合精品| 久久视频在线免费观看| 狠狠色丁香久久婷婷综合丁香 | 久久一区二区三区四区| 欧美大尺度在线| 亚洲欧美韩国| 亚洲精品一二区| 国产欧美一区二区三区久久人妖| 欧美在线观看视频| 久久亚洲欧洲| 在线观看91久久久久久| 亚洲最快最全在线视频| 欧美日韩另类字幕中文| 亚洲视频二区| 亚洲字幕一区二区| 国产精品高潮呻吟久久av无限| 欧美日韩精品免费观看视频| 久久国产日韩| 欧美精品色一区二区三区| 欧美国产日韩亚洲一区| 欧美三级视频在线| 欧美一区二区三区日韩| 欧美中文字幕视频| 亚洲免费成人av| 欧美一区二区日韩| 中国成人在线视频| 亚洲国产日韩在线一区模特| 亚洲一区二区三区免费视频| 亚洲国产精品第一区二区三区| 国产午夜精品理论片a级大结局| 欧美三级电影网| 欧美影院精品一区| 国产日韩欧美一区二区三区在线观看| 噜噜爱69成人精品| 欧美精品色网| 噜噜爱69成人精品| 欧美激情一区在线观看| 欧美激情欧美狂野欧美精品 | 国产美女精品| 国产欧美日韩在线播放| 国产亚洲精品久久久久动| 狠狠狠色丁香婷婷综合激情| 亚洲经典视频在线观看| 亚洲午夜极品| 欧美一区三区三区高中清蜜桃| 久久www免费人成看片高清| 久久综合久久综合这里只有精品| 女同一区二区| 午夜精品久久久久影视| 欧美v亚洲v综合ⅴ国产v| 久久精品国内一区二区三区| 亚洲电影第三页| 亚洲午夜91| 欧美激情女人20p| 国内精品久久久久影院 日本资源| 亚洲人在线视频| 美女图片一区二区| 一区二区三区日韩精品| 免费在线播放第一区高清av| 国产日韩一区二区三区在线| 亚洲视频视频在线| 欧美成人性网| 久久精品72免费观看| 国产色综合久久| 欧美一区二区三区免费观看视频| 91久久在线播放| 欧美激情第3页| 99re亚洲国产精品| 亚洲精品字幕| 国产精品区二区三区日本| 亚洲精品视频在线观看免费| 欧美国产第一页| 欧美激情综合| 亚洲欧美国产精品桃花| 欧美一级午夜免费电影| 在线看成人片| 99视频在线精品国自产拍免费观看| 欧美日韩一区二区视频在线| 一区二区三区视频观看| 午夜精品一区二区在线观看| 加勒比av一区二区| 欧美激情第二页| 国产精品丝袜xxxxxxx| 久久午夜电影网| 欧美午夜精品理论片a级大开眼界| 欧美一区二区在线免费播放| 免费的成人av| 久久一区二区三区四区| 欧美久久精品午夜青青大伊人| 亚洲自拍电影| 欧美激情精品久久久久久黑人| 亚洲淫性视频| 欧美另类视频在线| 欧美v国产在线一区二区三区| 欧美日韩国语| 亚洲国产精品一区| 亚洲影院免费| 午夜精品剧场| 国产精品高潮呻吟久久av无限 | 亚洲欧美综合v| 欧美18av| 亚洲高清精品中出| 狠狠色狠狠色综合人人| 这里只有精品电影| 亚洲色图在线视频| 欧美久久久久久久久久| 亚洲精品乱码久久久久久日本蜜臀| 国产一区二区精品久久99| 欧美一区二区视频在线观看2020|