C++MFC編程筆記day07 MFC的檔案操作、序列化和儲存,mfcday07
一 MFC的檔案操作
1 相關類
CFile類-封裝了檔案控制代碼以及操作檔案的API函數。
CFileFind類-提供檔案尋找功能。
2 CFile類的使用
2.1 開啟或者建立檔案
CFile::Open
2.2 檔案讀寫
注意:1 檔案指標位置 2 異常處理
CFile::Write
CFile::Read
CFile::SeekToBegin
2.3 關閉檔案
CFile::Close
2.4 設定/擷取檔案屬性
CFile::SetStatus/GetStatus
3 CFileFind類的使用
3.1 開始尋找,返回值代表是否有檔案存在
CFileFind::FindFile
3.2 擷取找到的第一個檔案資訊,返回下一個檔案是否存在
CFileFind::FindNextFile
3.3 擷取檔案資訊和判斷檔案資訊
CFileFind::GetXXX/IsXXX
3.4 結束尋找
CFileFind::Close
例子:1 使用該類尋找C:根目錄下所有的檔案和檔案夾
注意:磁碟根目錄中不存在.目錄,只有在下一層目錄中才
存在.目錄。
2 使用該類尋找C:下所有的檔案和檔案夾
2.1 遞迴,判斷如果是目錄,調用函數本身
strPath=find.GetFilePath()
2.2 排除.目錄
IsDots
二 序列化
1 概念
將資料以二進位流的方式依次寫入到檔案和從檔案中讀取資料的過程。
2 相關類
CFile類
CArchive類-歸檔類,提供了具體的資料讀寫的功能。
引入該類的好處,一,可以設定讀寫時的緩衝區;二,支援多種資料
類型的讀寫。
3 讀寫操作
3.1 開啟或者建立檔案
CFile::Open
3.2 檔案讀寫
3.2.1 定義CArchive類的對象
3.2.2 讀寫操作符函數
<< 寫操作
>> 讀操作
3.2.3 關閉
3.3 關閉檔案CArchive類的對象
CFile::Close
三 對象的序列化(第6個機制)
引入對象的序列化,解決使用者自訂類的對象的讀寫
1 概念
序列化對象(object store)
將對象的類的資訊和對象的成員變數依次寫入到檔案的過程。
還原序列化對象(object load)
從檔案首先讀取類的資訊,建立對象,然後讀取成員變數的值初始化
對象的過程。
結論:對象的序列化以運行時類資訊和動態建立為基礎的
2 使用
2.1 定義支援序列化的類 **
2.1.1 必須是CObject類的子類
2.1.2 添加序列化的聲明宏和實現宏
2.1.3 重寫虛函數 CObject::Serialize,在函數中,完成
類中的成員變數的序列化。
2.2 使用步驟與一般的資料類似
具體讀寫操作時,參數是對象的地址
3 原理
3.1 成員
_init_CStudent-結構體類型的成員對象,當定義該對象時,就會將
當前類的運行時類資訊儲存到應用程式中。
struct AFX_CLASSINIT
{
AFX_CLASSINIT(CRuntimeClass* pNewClass)
{
AfxClassInit(pNewClass);
{
//擷取應用程式類的模組狀態資訊
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
//儲存當前類的運行時類資訊(classCstudent的地址)
pModuleState->m_classList.AddHead(pNewClass);
AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
}
};
};
3.2 序列化對象的過程
ar.WriteObject(pOb);
{
//1 擷取當前類的運行時類資訊
CRuntimeClass* pClassRef = pOb->GetRuntimeClass();
//2 將類的資訊寫入到檔案
WriteClass(pClassRef);
{
pClassRef->Store(*this);
{
//依次將類的版本,類名稱長度以及類的名稱寫入檔案
WORD nLen = (WORD)lstrlenA(m_lpszClassName);
ar << (WORD)m_wSchema << nLen;
ar.Write(m_lpszClassName, nLen*sizeof(char));
}
}
//3 調用Serilize函數儲存物件的成員變數
((CObject*)pOb)->Serialize(*this);
{
//首先調用父類的序列化函數
CObject::Serialize( ar );
if (ar.IsStoring())//儲存操作
{
ar<<m_strName<<m_nAge;
}
else//載入操作
{
ar>>m_strName>>m_nAge;
}
}
}
3.3 還原序列化對象的過程
ar.ReadObject(RUNTIME_CLASS(CStudent));
{
//1 讀取當前類的運行時類資訊,得到運行時類資訊變數的地址
ReadClass(pClassRefRequested, &nSchema, &obTag);
{
// 從檔案中讀取類的資訊,比較並得到運行時類資訊
pClassRef = CRuntimeClass::Load(...)
{
//讀取類的名稱
ar.Read(szClassName, nLen*sizeof(char));
//遍曆鏈表,根據類的名稱,尋找運行時類資訊
for (pClass = pModuleState->m_classList; pClass != NULL;
pClass = pClass->m_pNextClass)
{
//具體的比較類的名稱
if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)
{
return pClass;
}
}
}
}
// 2 根據得到的運行時類資訊,動態建立對象
pOb = pClassRef->CreateObject();
//3 從檔案中讀取成員變數初始化建立的對象
pOb->Serialize(*this);
{
//首先調用父類的序列化函數
CObject::Serialize( ar );
if (ar.IsStoring())//儲存操作
{
ar<<m_strName<<m_nAge;
}
else//載入操作
{
ar>>m_strName>>m_nAge;
}
}
}
程式樣本:
建立win32控制台程式 ,添加afxwin.h標頭檔,設定包含MFC動態庫
主程式碼如下:
// MFCfile.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <AFXWIN.H>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//列印檔案狀態資訊void show_status(CFileStatus& status){printf("檔案名稱:%s\n",status.m_szFullName);printf("大小:%g\n",status.m_size);}//列印空格 ,為了清楚地顯示目錄結構void printspace(int n){if(n>0){for(int i=0;i<n;i++) printf(" ");}}//檔案讀取和寫入void CFileTest(){CFile file;//定義CFile對象//開啟CString filename="MFCfile.txt";BOOL bresult=file.Open(filename,CFile::modeCreate|CFile::modeReadWrite);if(!bresult) return;//開啟失敗,直接返回try{CString str="Hello my cfile!";file.Write(str,str.GetLength());printf("寫入成功\n");char sztxt[100]={0};file.SeekToBegin();//將檔案指標移動到檔案開頭file.Read(sztxt,100);printf("讀取成功,字串:%s\n",sztxt);file.Close();CFileStatus status;//如果其他程式正在使用該檔案,有可能出CFileException異常CFile::GetStatus(filename,status);//擷取狀態資訊show_status(status);CTimeSpan span(7,0,0,0);//時間間隔,7天status.m_ctime-=span;//修改建立時間提前7天CFile::SetStatus(filename,status);//設定狀態資訊}catch (CMemoryException* e){printf("記憶體出錯\n");}catch (CFileException* e){printf("檔案操作出錯\n");}catch (CException* e){printf("其他錯誤\n");}}//檔案尋找void CFileFindTest(CString strPath,int space=0){CFileFind cf;BOOL result=cf.FindFile(strPath+"\\*.*");//目錄後要加萬用字元while(result){result=cf.FindNextFile();CString filename=cf.GetFileName();printspace(space);if(cf.IsDirectory()) {if(!cf.IsDots()){CString filepath=cf.GetFilePath();//printf(" subdir:%s\n",filepath);CFileFindTest(filepath,space+1);}printf("目錄名:%s\n",filename);}else printf("檔案名稱:%s\n",filename);}cf.Close();}//序列化(二進位),寫入資料void CArchiveStoreTest(){CFile file;//定義CFile對象//開啟CString filename="MFCfile1.txt";BOOL bresult=file.Open(filename,CFile::modeCreate|CFile::modeWrite);if(!bresult) return;//開啟失敗,直接返回CArchive ar(&file,CArchive::store);ar<<100<<12.46<<"hello archive!";//寫入ar.Close();file.Close();}//序列化(二進位),讀取資料void CArchiveloadTest(){CFile file;//定義CFile對象//開啟CString filename="MFCfile1.txt";BOOL bresult=file.Open(filename,CFile::modeNoTruncate|CFile::modeRead);if(!bresult) return;//開啟失敗,直接返回CArchive ar(&file,CArchive::load);int i;double d;CString str;ar>>i>>d>>str;//讀取ar.Close();file.Close();printf("%d,%f,%s\n",i,d,str);}//1 定義支援序列化的類class CStudent:public CObject{public:virtual void Serialize( CArchive& ar );//重寫虛函數CStudent(){}CStudent(CString strName,UINT nAge){m_strName=strName;m_nAge=nAge;}void Show(){printf("姓名:%s\n",m_strName);printf("年齡:%d\n",m_nAge);}public:CString m_strName;UINT m_nAge;//序列化的宏DECLARE_SERIAL(CStudent)/* //宏內容_DECLARE_DYNCREATE(CStudent) AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, CStudent* &pOb);*/};IMPLEMENT_SERIAL(CStudent,CObject,1)/* //宏內容CObject* PASCAL CStudent::CreateObject() { return new CStudent;} _IMPLEMENT_RUNTIMECLASS(CStudent, CObject, 1, CStudent::CreateObject)AFX_CLASSINIT _init_CStudent(RUNTIME_CLASS(CStudent));CArchive& AFXAPI operator>>(CArchive& ar, CStudent* &pOb){ pOb = (CStudent*) ar.ReadObject(RUNTIME_CLASS(CStudent)); return ar; } */void CStudent::Serialize( CArchive& ar ){//首先調用父類的序列化函數CObject::Serialize( ar );if (ar.IsStoring())//儲存操作{ar<<m_strName<<m_nAge;}else//載入操作{ar>>m_strName>>m_nAge;}}//存入void ObjectStore(CStudent & stu){CFile file;file.Open("C:\\stu.dat",CFile::modeCreate|CFile::modeWrite);CArchive ar(&file,CArchive::store);ar<<&stu;ar.Close();file.Close();}//讀出void ObjectLoad(){CFile file;file.Open("C:\\stu.dat",CFile::modeRead);CArchive ar(&file,CArchive::load);CStudent *pStu=NULL;ar>>pStu;ar.Close();file.Close();if (pStu){pStu->Show();}}int main(int argc, char* argv[]){ //CFileTest();//CFileFindTest("../../");CArchiveStoreTest();CArchiveloadTest();CStudent stu("student1",23); ObjectStore(stu);ObjectLoad();getchar();return 0;}
mfc序列化(序列化)儲存怎去實現
沒有現成的儲存方法
建議使用 boost 的 序列化庫 www.boost.org/
參考序列化庫的教程 dozb.bokee.com/1692310.html
VC++ MFC CArchive類與序列化操作問題
可以。MFC下標準變數類型,和支援序列化的類都可以這麼做。CString是支援序列化的。