當我們創建對象的時候,對象就存在于內存中,當其生命周期結束后,這些被創建的對象就要被銷毀;當對象被銷毀后,我們就無法知道這些對象的值。MFC提供了CArchive類可以將對象數據保存到永久設備,比如磁盤文件。當應用程序重新啟動后,CArchive類可以幫助我們從磁盤文件讀取這些數據,然后在內存中重新構建對應的對象;這樣就使得我們的對象數據永久存在,該過程稱之為序列化(或者串行化)。
CArchive類沒有基類,一個CArchive對象以一種有效的、非冗余的格式處理二進制對象數據;當構造一個CArchive對象后,就可以將它與一個打開的CFile類或者派生類對象相關聯,并且一個CFile對象只能和一個活動的歸檔對象相關聯。在創建CArchive對象之前,必須先創建一個CFile類或者其派生類對象;同時我們需要確保這個CFile對象的打開方式和該歸檔對象(CArchive)的加載/保存狀態保存一致。
CArchive類對象可以處理基本的數據類型,比如int,float,CString等,還可以處理CObject類的派生類;CArchive類重載了提取(>>)和插入(<<)操作符,這兩個操作符可以支持基本類型,也可支持CObject的派生類;提取(>>)操作符是從文件中加載CObject類對象和基本數據類型,插入(<<)操作符是從文件中讀取CObject類對象和基本數據類型。
CArchive類的構造函數如下:
CArchive(CFile* pFile,UINT nMode,int nBufSize=4096,void* lpBuf=NULL );參數: pFile CFile對象的指針。CFile對象是永久數據的最終的源或目標。 nMode 它指定了對象是否從歸檔文件中裝載或存儲到文件中去。nMode參數必須有下列值之一: · CArchive::load 從歸檔文件裝載數據。CFile只讀。 · CArchive::store 把數據保存到歸檔文件中。允許CFile寫操作。 · CArchive::bNoFlushOnDelete 當歸檔文件析構程序被調用時,防止歸檔文件自動調用Flush。如果設定了此標識,則在析構程序被調用之前必須負責調用Close。如果不這樣做,數據就會崩潰。 nBufSize
指定內部文件緩沖區大小的整數,以字節計算。注意缺省的緩沖區大小為4096字節。如果例程歸檔大的對象,使用大一些的緩沖區,即多個文件緩沖區,那么將會提高例程的執行效率。 lpBuf
指向nBufSize大小的提供緩沖區的指針。如果不指定這個參數,歸檔文件從本地堆為歸檔文件分配一個緩沖區并且當對象被毀棄時,釋放緩沖區。歸檔文件不能釋放一個提供的緩沖區。
實例
我們創建一個Serialize的單文檔工程,并在菜單欄上創建兩個菜單項,一個是讀文件,一個是寫文件,在利用歸檔對象讀寫數據的時候,需要保證讀寫的對象順序一致,它們的消息響應函數如下;
//自定義的CFile派生類對象,方便觀察結果
class CUseFile:public CFile{public: //派生類才支持二進制讀寫 CUseFile(LPCSTR strFileName,UINT nMode):CFile(strFileName,nMode){};};//加載對象數據
void CSerializeView::OnRead(){ // TODO: 在此添加命令處理程序代碼 CUseFile File("test.txt",CFile::modeRead|CFile::typeBinary); CArchive ar(&File, CArchive::load); int nStudentID = 0; CString strName= ""; float fAverageScore = 0.0f; //讀取對象的數據,需要和寫入的順序一致 ar >> nStudentID >> strName >> fAverageScore; //顯示讀取的內容 CString strLoadInfo; strLoadInfo.Format("ID = %d, Name = %s, Score = %.2f",nStudentID, strName, fAverageScore); MessageBox(strLoadInfo);}//保存對象數據
void CSerializeView::OnWrite(){ // TODO: 在此添加命令處理程序代碼 CFile File("test.txt", CFile::modeCreate|CFile::modeWrite|CFile::typeBinary); CArchive ar(&File, CArchive::store); //將要保存的數據 int nStudentID = 16; CString strName= "Mike"; float fAverageScore = 90.1f; //保存數據到歸檔對象 ar << nStudentID << strName << fAverageScore;}運行結果:
UltraEdit工具打開,可以觀察到我們保存的數據。
序列化使得我們的數據得以保存和讀取,具有了數據庫保存數據的功能,因此對于記錄少量的數據我們就可采用MFC的的序列化進行數據的存儲和讀取。
附錄
CArchive類的成員數據成員
| m_pDocument | 指向被串行化的CDocument對象 |
| CArchive | 創建一個CArhcive對象 |
| Abort | 在不異常的情況下,關閉歸檔文件 |
| Close | 沖掉未寫入數據并且釋放與CFile的連接 |
| Flush | 從歸檔文件緩沖區中沖掉未寫入數據 |
| Operator >> | 裝載對象和歸檔文件的主要類型 |
| operator << | 存儲對象和歸檔文件的主要類型 |
| Read | 讀入原始類型 |
| Write | 寫入原始類型 |
| WriteString | 寫一行文本 |
| ReadString | 讀一行文本 |
| GetFile | 獲得此歸檔文件的CFile對象指針 |
| GetObjectSchema | 由Serialize函數調用來確定被非串行化的對象的版本 |
| SetObjectSchema | 在歸檔文件中存儲對象概要 |
| IsLoading | 確定歸檔文件是否被裝載 |
| IsStoring | 確定歸檔文件是否被存儲 |
| IsBufferEmpty | 確定在一個Windows Socket接收過程中緩沖區是否被清空 |
| ReadObject | 調用一個用于裝載的Serialize函數 |
| WriteObect | 調用一個用于裝載的Serialize函數 |
| MapObject | 在沒有對文件串行化的映射中放置對象,但是此映射對參考的子對象有效 |
| SetStoreParams | 設置哈希表的大小和映射的塊的大小,在串行化的過程中識別唯一的對象 |
| LoadParams | 設置裝載數組擴展的大小。必須在被裝載對象之前或調用MapObject或ReadObject之前 |
| ReadClass | 讀入一個原先存儲在WriteClass中的類的參考 |
| WriteClass | 把對CRuntime的參考寫入CArchive |
| SerializeClass | 根據CArchive方向,讀入或寫入對CArchive對象的類的參考 |
|
新聞熱點
疑難解答