下面介紹一種特殊的檔案操作方式——CArchive。
CArchive
的介紹:
Allows you to save a complex network of objects in a permanent binary form (usually disk storage) that persists after those objects are deleted.
CArchive
does not have a base class.
Later you can load the objects from persistent storage, reconstituting them in memory. This process of making data persistent is called "serialization."
從這些話中我們可以得知,CArchive使用了緩衝區,即一段記憶體空間作為臨時資料存放區地,對CArchive的讀寫都先依次排列到此緩衝區,當緩衝區滿或使用者要求時,將此段整 理後的資料讀寫到指定的儲存煤質。 當建立CArchive對象時,應指定其模式是用於緩衝區讀,還是用於緩衝區寫。
一般情況下建立 CArchive 對象有兩種方法:
- 通過架構隱式建立 CArchive 對象
- 顯式建立 CArchive 對象
一.
通過架構隱式建立 CArchive
對象
最普通且最容易的方法是使架構代表[檔案] 功能表上的“儲存”、“另存新檔”和“開啟”命令為文檔建立 CArchive 對象。
以下是應用程式的使用者從[檔案] 功能表上發出“另存新檔”命令時,架構所執行的操作:
- 顯示“另存新檔”對話方塊並從使用者擷取檔案名稱。
- 開啟使用者命名的檔案作為 CFile
對象。
- 建立指向該 CFile
對象的 CArchive
對象。在建立 CArchive
對象時,架構將模式設定為“儲存”(即寫入或序列化),而不是“載入”(即讀取或還原序列化)。
- 調用在 CDocument
衍生類別中定義的 Serialize
函數,將 CArchive
對象的引用傳遞給該函數。
然後,文檔的 Serialize 函數將資料寫入 CArchive 對象(剛作瞭解釋)。從 Serialize 函數返回時,架構先銷毀 CArchive 對象,再銷毀 CFile 對象。
因此,如果讓架構為文檔建立 CArchive 對象,您所要做的一切是實現寫入存檔和從存檔中讀取的文檔的 Serialize 函數。您還必須為文檔的 Serialize 函數直接或間接依次序列化的任何 CObject 派生對象實現 Serialize。
顯 式建立 CArchive 對象
除了通過架構將文檔序列化之外,在其他場合也可能需要 CArchive 對象。例如,可能要序列化到達或來自剪貼簿的資料,由 CSharedFile 對象表示。或者,可能要使用使用者介面來儲存與架構提供的檔案不同的檔案。在這種情況下,可以顯式建立 CArchive 對象。使用下列過程,用與架構採用的相同方式來執行此操作。
二.
顯式建立 CArchive
對象
構造 CFile
對象或從 CFile
匯出的對象。
- 按照下面樣本所示,將 CFile
對象傳遞到 CArchive
的建構函式:
CFile theFile;
theFile.Open(..., CFile::modeWrite);
CArchive archive(&theFile, CArchive::store);
CArchive 建構函式的第二個參數是指定存檔將用於向檔案中儲存資料還是用於從檔案中載入資料的枚舉值。對象的 Serialize 函數通過調用存檔對象的 IsStoring 函數來檢查該狀態。
當完成向 CArchive Object Storage Service資料或從該對象中載入資料時,關閉該對象。雖然 CArchive 對象(和 CFile 對象)會自動關閉存檔(和檔案),好的做法是顯式執行,因為這使從錯誤恢複更為容易。
最後關閉 CArchive 對象
archive.Close();
theFile.Close();
下面使用一個簡單樣本來說明:
讀檔案:
char filename[50];<br />cout<<"Pleast input the file name you want to Read:/n";<br />cin>>filename;<br />WCHAR wszfileName[256]; // Unicode user name<br />// Convert ANSI filename to Unicode<br />MultiByteToWideChar( CP_ACP, 0, filename,<br />strlen(filename)+1, wszfileName,<br />sizeof(wszfileName)/sizeof(wszfileName[0]) );<br />CFile myFile(wszfileName, CFile::modeRead);<br />CArchive ar(&myFile, CArchive::load); //注意選擇合適的方式,load為讀<br />int n;<br />float f;<br />CString str;<br />if (ar.IsLoading())<br />{<br />//通過>>來讀取,順序必須和寫入順序相同<br />ar>>n>>f>>str; </p><p>cout<<n<<endl;<br />cout<<f<<endl;<br />wcout<<(LPCTSTR)str<<endl;<br />//read<br />char readBuf[100];<br />ar.Read(readBuf, 100);</p><p>cout<<readBuf;<br />//readstring<br />ar.ReadString(str);<br />wcout<<(LPCTSTR)str<<endl;<br />ar.ReadString(str);<br />wcout<<(LPCTSTR)str<<endl;<br />}<br />ar.Close();<br />myFile.Close();
寫檔案:
cout<<"Pleast input the file name you want to Write:/n";<br />char filename[50];<br />cin>>filename;<br />WCHAR wszfileName[256]; // Unicode user name<br />// Convert ANSI filename to Unicode<br />MultiByteToWideChar( CP_ACP, 0, filename,<br />strlen(filename)+1, wszfileName,<br />sizeof(wszfileName)/sizeof(wszfileName[0]) );<br />CFile myFile(wszfileName, CFile::modeCreate | CFile::modeReadWrite);</p><p>CArchive ar(&myFile, CArchive::store); //注意選擇合適的方式,store為寫<br />int n = 10;<br />float f = 2.4f;<br />CString str("Hello CArchive!");<br />CString str1("String1"), str2("String2");<br />char writeBuf[100] = "Write Character!/n";<br />if (ar.IsStoring())<br />{<br />//通過<<寫入<br />ar<<n<<f<<str;<br />//Write<br />ar.Write(writeBuf, 100);<br />// Write str1 and str2 to the archive<br />ar.WriteString(str1);<br />ar.WriteString(_T("/n"));<br />ar.WriteString(str2);<br />ar.WriteString(_T("/n"));<br />}<br />ar.Close();<br />myFile.Close();
除此之外,CArchive還可以寫如類對象等資料。我們可以通過WriteClass(),WriteObject()和起配套的ReadClass(),ReadObject()來進行讀寫。如下面的例子:
WriteClass()/ReadClass():
CFile myFile(_T("Myfile.dat"),<br /> CFile::modeCreate | CFile::modeReadWrite);<br />// Create a storing archive.<br />CArchive arStore(&myFile, CArchive::store);<br />// Store the class CAge in the archive.<br />arStore.WriteClass(RUNTIME_CLASS(CAge));<br />// Close the storing archive.<br />arStore.Close();<br />// Create a loading archive.<br />myFile.SeekToBegin();<br />CArchive arLoad(&myFile, CArchive::load);<br />// Load a class from the archive.<br />CRuntimeClass* pClass = arLoad.ReadClass();<br />if (!pClass->IsDerivedFrom(RUNTIME_CLASS(CAge)))<br />{<br /> arLoad.Abort();<br />}<br />
WriteObject()/ReadObject():
CFile myFile(_T("Myfile.dat"),<br /> CFile::modeCreate | CFile::modeReadWrite);<br />CAge age(21), *pAge;<br />// Create a storing archive.<br />CArchive arStore(&myFile, CArchive::store);<br />// Write the object to the archive<br />arStore.WriteObject(&age);<br />// Close the storing archive<br />arStore.Close();<br />// Create a loading archive.<br />myFile.SeekToBegin();<br />CArchive arLoad(&myFile, CArchive::load);<br />// Verify the object is in the archive.<br />pAge = (CAge*) arLoad.ReadObject(RUNTIME_CLASS(CAge));<br />ASSERT(age == *pAge);<br />
CArchive是MFC封裝的一個非常有用的檔案處理類,我們可以在我們需要序列化資料處理的時候使用他。
對於CArchive類的其他使用和詳細資料,可參考MSDN上的說明。