轉(zhuǎn)帖|使用教程|編輯:鮑佳佳|2021-06-28 10:27:52.563|閱讀 161 次
概述:本節(jié)介紹下Visual c++/MFC界面開發(fā)中文件操作類CFile類的使用。Windows系統(tǒng)的API函數(shù)除了ReadFile,還有CreateFile、WriteFile等函數(shù)。而MFC基于面向?qū)ο蟮乃枷耄瑢⑦@些Windows API函數(shù)封裝到了CFile類中,實(shí)現(xiàn)對(duì)文件的打開、關(guān)閉、讀、寫、獲取文件信息等操作。使用CFile類對(duì)文件進(jìn)行操作非常便捷。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
上一節(jié)中講了定時(shí)器Timer的用法,本節(jié)介紹下Visual c++/MFC界面開發(fā)中文件操作類CFile類的使用。在內(nèi)容開始前為大家介紹兩款MFC界面開發(fā)控件:
如果你學(xué)過C語言,應(yīng)該知道文件操作使用的是文件指針,通過文件指針實(shí)現(xiàn)對(duì)它指向的文件的各種操作。這些文件操作函數(shù)中有的最終還是調(diào)用了操作系統(tǒng)的API函數(shù)或者處理過程與之類似,例如在Windows系統(tǒng)中,fread函數(shù)就調(diào)用了API函數(shù)ReadFile。
Windows系統(tǒng)的API函數(shù)除了ReadFile,還有CreateFile、WriteFile等函數(shù)。而MFC基于面向?qū)ο蟮乃枷耄瑢⑦@些Windows API函數(shù)封裝到了CFile類中,實(shí)現(xiàn)對(duì)文件的打開、關(guān)閉、讀、寫、獲取文件信息等操作。使用CFile類對(duì)文件進(jìn)行操作非常便捷。
CFile( );
CFile(HANDLE hFile);
CFile(LPCTSTR lpszFileName,UINT nOpenFlags);
以上三個(gè)成員函數(shù)都是CFile的構(gòu)造函數(shù),用于構(gòu)造CFile對(duì)象。參數(shù)hFile為要關(guān)聯(lián)到CFile對(duì)象的文件的句柄。參數(shù)lpszFileName為要關(guān)聯(lián)到CFile對(duì)象的文件的相對(duì)路徑或者絕對(duì)路徑;參數(shù)nOpenFlags為文件訪問選項(xiàng)的組合,通過各選項(xiàng)的按位或運(yùn)算實(shí)現(xiàn)組合,下面的5個(gè)表列出了nOpenFlags參數(shù)可能取的選項(xiàng):
下面的文件訪問模式選項(xiàng)表中只能選擇一個(gè)進(jìn)行組合,默認(rèn)取CFile::modeRead。
取值 | 描述 |
CFile::modeRead | 只讀方式訪問文件 |
CFile::modeWrite | 寫入方式訪問文件 |
CFile::modeReadWrite | 讀寫方式訪問文件 |
下面的文件共享模式選項(xiàng)表中也只能選擇一個(gè)進(jìn)行組合,默認(rèn)的共享模式是CFile::shareExclusive。
取值 | 描述 |
CFile::shareDenyNone | 允許其他進(jìn)程對(duì)文件進(jìn)行讀寫 |
CFile::shareDenyRead | 不允許其他進(jìn)程讀取文件 |
CFile::shareDenyWrite | 不允許其他進(jìn)程寫文件 |
CFile::shareExclusive | 禁止其他進(jìn)程對(duì)文件的所有訪問 |
下面的文件創(chuàng)建模式選項(xiàng)列表中可選擇第一個(gè)或兩者都選進(jìn)行組合。
取值 | 描述 |
CFile::modeCreate | 如果文件不存在則創(chuàng)建文件,而如果存在則將它關(guān)聯(lián)到此CFile對(duì)象并將長度截取為0 |
CFile::modeNoTruncate | 如果文件不存在則創(chuàng)建文件,而如果存在則將它關(guān)聯(lián)到此CFile對(duì)象而不進(jìn)行截取 |
注意,選擇CFile::modeNoTruncate時(shí)需要與CFile::modeCreate一起使用,即CFile::modeCreate | CFile::modeNoTruncate。
另外,還有一個(gè)文件緩沖選項(xiàng)列表和一個(gè)文件安全選項(xiàng)。文件緩沖選項(xiàng)不太常用,雞啄米這里就不講了,有興趣的可以查閱MSDN。文件安全選項(xiàng)是CFile::modeNoInherit,意為禁止子進(jìn)程繼承使用此文件。
當(dāng)然,在實(shí)際使用時(shí),以上各個(gè)表并不是都要用到,大家可以根據(jù)自己的需要選擇用哪個(gè)表,選擇哪個(gè)選項(xiàng)。
virtual BOOL Open(LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError = NULL);
打開文件。它通常與默認(rèn)構(gòu)造函數(shù)CFile::CFile()一起使用。參數(shù)lpszFileName和nOpenFlags同構(gòu)造函數(shù)。參數(shù)pError為指向文件異常對(duì)象的指針,默認(rèn)為NULL。
virtual void Close( );
關(guān)閉文件。如果你沒有在執(zhí)行析構(gòu)函數(shù)前調(diào)用此成員函數(shù)關(guān)閉文件,則析構(gòu)函數(shù)會(huì)為你關(guān)閉。
virtual UINT Read(void* lpBuf,UINT nCount);
讀取文件數(shù)據(jù)到緩存。參數(shù)lpBuf是由用戶提供的指向接收文件數(shù)據(jù)的緩存的指針;參數(shù)nCount為讀取的最大字節(jié)數(shù)。返回值是實(shí)際讀取到緩存的字節(jié)數(shù),如果到達(dá)文件尾則返回值可能會(huì)小于nCount,此時(shí)繼續(xù)讀取的話,會(huì)返回0,所以通常我們都會(huì)判斷返回值是否小于nCount或者等于0來確定是否到達(dá)文件尾。
virtual void Write(const void* lpBuf,UINT nCount);
將緩存中的數(shù)據(jù)寫入文件。參數(shù)lpBuf也是由用戶提供,指向包含寫入數(shù)據(jù)的緩存的指針;參數(shù)nCount為緩存中要被寫入文件的數(shù)據(jù)的字節(jié)數(shù)。
virtual ULONGLONG Seek(LONGLONG lOff,UINT nFrom);
在一個(gè)打開的文件中重定位文件指針。參數(shù)lOff為文件指針移動(dòng)的字節(jié)個(gè)數(shù),為正數(shù)時(shí)表示向文件尾移動(dòng),為負(fù)數(shù)時(shí)表示向文件開頭移動(dòng);參數(shù)nFrom為lOff的基準(zhǔn)位置,即由nFrom位置開始移動(dòng)lOff個(gè)字節(jié),它可以取下面幾個(gè)值中的一個(gè):
CFile::begin 從文件開頭開始移動(dòng)
CFile::current 從文件指針的當(dāng)前位置開始移動(dòng)
CFile::end 從文件尾開始移動(dòng)
文件打開時(shí),文件指針被置于0,即文件開頭處。
如果此函數(shù)成功則返回文件指針的位置。
void SeekToBegin( );
將文件指針移動(dòng)到文件開頭。它等價(jià)于Seek( 0L, CFile::begin )。
ULONGLONG SeekToEnd( );
將文件指針移動(dòng)到文件末尾。返回值是文件的字節(jié)長度。它等價(jià)于CFile::Seek( 0L, CFile::end )。
virtual ULONGLONG GetLength( ) const;
獲取文件的字節(jié)長度。
virtual void SetLength(ULONGLONG dwNewLen);
改變文件的長度。參數(shù)dwNewLen為文件的新長度,它可能比文件的當(dāng)前長度值要大或者小,文件會(huì)相應(yīng)的被擴(kuò)展或截取。
virtual CString GetFileName( ) const;
獲取文件名稱。
virtual CString GetFilePath( ) const;
獲取文件的絕對(duì)路徑。
virtual CString GetFileTitle( ) const;
獲取文件的顯示名稱。舉個(gè)例子,與GetFileName區(qū)分一下,如果你系統(tǒng)中的文件不顯示擴(kuò)展名,則它獲取到的文件名稱就不包含擴(kuò)展名,否則就顯示擴(kuò)展名。
virtual ULONGLONG GetPosition( ) const;
獲取文件指針的當(dāng)前位置。
static void PASCAL Remove(LPCTSTR lpszFileName,CAtlTransactionManager* pTM = NULL);
刪除文件。參數(shù)lpszFileName為要?jiǎng)h除的文件路徑,可以是相對(duì)路徑、絕對(duì)路徑或者網(wǎng)絡(luò)路徑;參數(shù)pTM指向一個(gè)CAtlTransactionManager對(duì)象。
static void PASCAL Rename(LPCTSTR lpszOldName,LPCTSTR lpszNewName,CAtlTransactionManager* pTM = NULL);
重命名文件。參數(shù)lpszOldName為老的文件路徑;參數(shù)lpszNewName為新的文件路徑;參數(shù)pTM指向一個(gè)CAtlTransactionManager對(duì)象。實(shí)際上此函數(shù)的意義已經(jīng)不只是重命名文件,還可以移動(dòng)文件到其他目錄下,例如,lpszOldName取"d:\\1.txt",lpszNewName取"e:\\2.txt",這樣可以將D盤中的1.txt文件轉(zhuǎn)移到E盤并重命名為2.txt。
這里只給大家演示幾個(gè)簡(jiǎn)單的代碼片段,從這些代碼片段中熟悉CFile類的文件操作。
實(shí)例一:構(gòu)造CFile對(duì)象時(shí)就打開文件,然后向文件中寫入數(shù)據(jù),最后以Seek函數(shù)移動(dòng)文件指針,讀取文件內(nèi)容。
C++代碼
char writeBuffer[500]; // 要寫入的數(shù)據(jù)的緩存 char readBuffer[500]; // 存放讀取數(shù)據(jù)的緩存 LONGLONG lOff = 0; // 文件指針的偏移量,也是讀取到的數(shù)據(jù)的總字節(jié)數(shù) // 構(gòu)造CFile對(duì)象,同時(shí)以創(chuàng)建和讀寫的方式打開文件E:\1.txt CFile file(_T("e:\\1.txt"), CFile::modeCreate | CFile::modeReadWrite); // 將寫入數(shù)據(jù)的緩存中每個(gè)字節(jié)都賦值為字符c memset(writeBuffer, 'c', sizeof(writeBuffer)); // 將數(shù)據(jù)寫入到文件中 file.Write(writeBuffer, sizeof(writeBuffer)); while (true) { // 以文件開頭為基準(zhǔn),移動(dòng)文件指針到lOff的位置 file.Seek(lOff, CFile::begin); // 讀取100個(gè)字節(jié)的數(shù)據(jù)到存放讀取數(shù)據(jù)的緩存的readBuffer + lOff位置處 int nRet = file.Read(readBuffer + lOff, 100); // 根據(jù)實(shí)際讀取的字節(jié)數(shù),增加文件指針的移動(dòng)量 lOff += nRet; // 如果讀取數(shù)據(jù)時(shí)返回值小于指定的100,說明已到文件尾,跳出循環(huán) if (nRet < 100) break; } // 關(guān)閉文件 file.Close();
實(shí)際上,在Write函數(shù)和Read函數(shù)執(zhí)行后,文件指針會(huì)自動(dòng)移動(dòng)到最后操作的位置,所以其實(shí)上面的代碼中無須使用Seek函數(shù)再去手動(dòng)移動(dòng)文件指針。這將在下面的實(shí)例二中體現(xiàn)出來。
實(shí)例二:構(gòu)造CFile對(duì)象,然后使用Open成員函數(shù)打開文件,再寫入一個(gè)結(jié)構(gòu)體數(shù)組,最后讀取出來。
先貼上結(jié)構(gòu)體的定義:
C++代碼
struct student { int nNum; float fScore; };
下面是文件操作的代碼片段:
C++代碼
student s1[2]; // 存放要寫入文件的數(shù)據(jù) student s2[2]; // 存放從文件讀取的數(shù)據(jù) CFile file; // CFile對(duì)象 int nReadBytes = 0; // 從文件中讀取到的總字節(jié)數(shù) // 為s1數(shù)組各元素賦值 s1[0].nNum = 22; s1[0].fScore = 91.5; s1[1].nNum = 23; s1[1].fScore = 85; // 以創(chuàng)建、讀寫方式打開文件E:\1.txt if (file.Open(_T("E:\\1.txt"), CFile::modeCreate | CFile::modeReadWrite)) { // 寫入數(shù)據(jù)s1結(jié)構(gòu)體數(shù)組 file.Write(s1, sizeof(s1)); // 因?yàn)樯厦嬲{(diào)用Write以后文件指針在文件尾,所以需要將其移動(dòng)到文件開頭 file.SeekToBegin(); while (true) { // 讀取數(shù)據(jù)到s2 int nRet = file.Read((BYTE*)s2 + nReadBytes, sizeof(student)); // 計(jì)算已經(jīng)讀取到的總字節(jié)數(shù) nReadBytes += nRet; // 如果讀取數(shù)據(jù)時(shí)返回值小于指定的sizeof(student),則說明已到文件尾,跳出循環(huán) if (nRet < sizeof(student)) break; } // 關(guān)閉文件 file.Close(); }
本節(jié)內(nèi)容就到這里,如果有其他語言的文件操作的經(jīng)驗(yàn)的話,應(yīng)該還是比較簡(jiǎn)單的。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自: