MFC中的檔案讀寫操作

來源:互聯網
上載者:User

電腦室如何管理自身所存放著的大量的資訊的呢。windows的磁碟管理程式為我們提供了一套嚴密而又高效的資訊組織形式--硬碟上的資訊是以檔案的形式被管理的。

面向儲存的檔案技術

什麼是檔案。電腦中,一篇文章、一幅圖片、一個程式等都是以檔案的形式儲存在磁碟上的,每個檔案都有一個檔案名稱。電腦就是對檔案按名存取的。檔案名稱的格式如下:主檔案名.副檔名。 為什麼要在程式中使用檔案。

通常,程式中的資料在程式運行結束之後,就會從記憶體中清除,再次運行程式時不會自動出現。在編製程式的過程中不可避免的會遇到將某些資料永久儲存的問題,當程式關閉後,依然可以使用這些資料,這時就需要進行檔案操作。 檔案類型

Visual C++處理的檔案通常分為兩種:

文字檔:只可被任意文字編輯器讀取ASCII文本。

二進位檔案:

指對包含任意格式或無格式資料的檔案的統稱。

這裡只介紹文字檔的讀寫,INI檔案也屬於文字檔的範疇,且INI檔案的結構和用途與普通的文字檔不同,所以會單獨介紹。 第一部分:文字檔 文字檔的讀寫

認識CFile類;認識文字檔;能夠正確靈活應用文字檔存取資訊;避免文字檔讀寫的常見誤區。

CFile是MFC的檔案操作基本類,它直接支援無緩衝的二進位磁碟I/O操作,並通過其衍生類別支援文字檔、記憶體檔案和socket檔案。 客戶操作記錄執行個體功能預覽及關鍵知識點

許多系統,出於安全或其他原因,常常要求隨時對鍵盤進行監控,利用Hook(鉤子)技術編寫的應用程式能夠很好地達到這個目的。本軟體就製作了一個客戶操作記錄軟體,即在軟體運行過程中,使用者在鍵盤上的按鍵動作會被記錄下來,這樣對維護軟體的正常運行非常有利。

只要啟動客戶操作記錄軟體後,不管輸入焦點是否在本軟體上,按鍵都會被記錄下來。我們需要的是鍵盤的系統監控,只要本軟體在運行,無論當前電腦在做什麼,都能監測到使用者按鍵的行為並做出反應,這就要用到Hook技術。

Hook技術在很多特殊軟體中廣泛應用,如,金山詞霸的“取詞”功能,就用到了Hook計技術。

鉤子的本質是一段用以處理系統訊息的程式,通過系統調用,將其掛入系統。鉤子的種類很多,每種鉤子可以截獲並處理相應的訊息,每當特定的訊息發出,在到達目的視窗之前,鉤子程式先行截獲該訊息、得到對此訊息的控制權。此時在鉤子函數中就可以對截獲的訊息進行加工處理,甚至可以強制結束訊息的傳遞。

從鉤子的本質來看,可以優先截獲作業系統的各種訊息進行處理,所以它幾乎無所不能,因為windows的應用程式都是基於訊息驅動的,應用程式的操作都依賴於它所得到的訊息的類型及內容。

如果Hook過程在應用程式中實現,若應用程式不是當前視窗時,該Hook就補齊作用;如果Hook在DLL中實現,程式在運行中動態調用它,它能即時對系統進行監控。根據需要,我們採用的是在DLL中實現Hook的方式。

(應用程式exe? 和DLL的區別所在) 文字檔儲存管理

字元被電腦處理時都是以二進位代碼的形式出現的,即一個字元對應一個8位位元,這種二進位碼的集合就是所謂的ASCII碼。

基本的ASCII碼有128個,最高位都是0,對應的十進位數是0-127。鍵盤上的字元,如英文字母、數字和一些常用符號,使用基本ASCII部分。如數字“0”的ASCII碼用位元表示就是00110000(即十進位數48)。

擴充的ASCII碼有128個,最高位是1,對應的十進位數是128-255。一些定位字元和其他符號使用擴充的ASCII碼部分。

為解決漢字的儲存和顯示問題,我國制定了國際GB2312。據此規定,一個漢字由2個擴充的ASCII碼組成,這種高位為1的雙位元組漢字編碼就是漢字的機內碼,簡稱為內碼。例如,漢字“學”的機內碼用位元表示就是11010001 10100111(即十進位數206 和167 ),用十進位表示就是53671(206*256+167)。對於字元,文字檔儲存的是它的ASCII碼,對於漢字,文字檔儲存的是它的內碼,即兩位ASCII碼,如字串“0學0”,在文字檔中儲存的內容是00110000 11010001 10100111 00110000 正確的文字檔讀寫過程

1.定義檔案變數;2.開啟指定的檔案;3.向從文字檔中寫入資訊;4.從文字檔中讀取資訊;5.關閉檔案 1、定義檔案變數

定義檔案變數格式:CStdioFile 檔案變數;

例如,定義一個名稱為f1的檔案變數,語句如下:CStdioFile f1;

  2、開啟指定檔案

可以直接通過CStdioFile的建構函式來開啟磁碟檔案,同時可以用標誌位指定開啟檔案(唯讀、唯寫、讀寫等):

CStdioFile(LPCTSTR lpszFileName,UINT nOpenFlags);

其中,lpszFileName表示要開啟的檔案名稱,可以是相對路徑或絕對路徑

nOpenFlags設定檔案開啟檔案標誌位,可以指定用“|”串連多個標誌位。下面是常用的開啟標誌:

CFile::typeText:以文字檔的形式開啟檔案

CFile::typeBinary:以二進位檔案的形式開啟檔案

CFile::modeCreate:如果指定檔案名稱的檔案不存在,則建立檔案;如果檔案存在並且沒有設定CFile::modeNoTruncate標誌,則清空檔案。

CFile::modeNoTruncate:如果檔案存在,不把它的長度刪除為0(即不清空檔案中的資料)。

CFile::modeRead:以唯讀方式開啟檔案

CFile::modeReadWrite:以可讀可寫方式開啟檔案

CFile::modeWrite:以唯寫方式開啟檔案

CFile::shareDenyNone:檔案開啟後,不禁止其他進程對檔案的讀寫操作

CFile::shareExclusive:檔案開啟後,禁止其他進程對檔案的讀寫操作

CFile::shareDenyRead:檔案開啟後,禁止其他進程對檔案的讀操作

CFile::shareDenyWrite:檔案開啟後,禁止其他進程對檔案的寫操作

此外,可以不在建構函式中開啟檔案,而僅僅調用空的建構函式CStidoFile(),然後用CStdioFile::Open()開啟檔案。Open函數的前兩個參數和非空建構函式的參數相同,其聲明如下:

BOOL Open(LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError=NULL);

第3個參數與開啟失敗時的異常處理有關。 執行個體1:以唯讀方式開啟一個檔案

步驟:

使用AppWizard建立一個對話方塊應用程式,刪除其自動產生的所有控制項,添加一個Button控制項。雙擊控制項,在相應的函數裡添加代碼:

char * pszFileName="C://myfile.txt";CStdioFile myFile;CFileException fileException;if(!myFile.Open(pszFileName,CFile::modeCreate|CFile::typeText|CFile::modeRead),&fileException){    TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause);}

運行結果:如果C:/下沒有myfile.txt檔案,則新產生該檔案。 3.向從文字檔中寫入資訊

CStdioFile提供了函數WriteString來向文字檔中寫入文本,WriteString函數的格式如下:

void WriteString(LPCTSTR lpsz);

WriteString的參數lpsz是一個以”/0”字元結束的字串,要把這個字串的內容寫入檔案。

提示:使用WriteString函數時,如果希望每執行一次WriteString,文字檔中的內容就會自動換行一次,那麼就需要在需要換行的地方輸出“/n”:

myFile.WriteString(“第1行/n”); 執行個體2:向檔案中寫入文本

建立MFC基於對話方塊的程式,刪除自動添加的所有控制項,添加一個“確定”按鈕,雙擊按鈕,按預設添加事件函數,雙擊按鈕,在相應的函數處添加如下代碼:

char* pszFileName="C://myfile.txt";CStdioFile myFile;CFileException fileException;if(myFile.Open(pszFileName,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException){    myFile.WriteString("第1行/n");    CString strOrder;    strOrder.Format("%d,%.3f",66,88.88);    myFile.WriteString(strOrder);}else{    TRACE("Can't open file %s,error=%u/n",pszFileName,fileException.m_cause);}

程式運行結果:C:/myfile.txt檔案中內容如下:

第1行

66,88.880 4.從文字檔中讀取資訊

CStidoFile提供了函數ReadString來讀取文本,ReadString有兩種形式,一種為:

virtual LPTSTR ReadString(LPTSTR lpsz, UINIT nMax);

ReadString函數的參數如下:

lpsz :是使用者提供的一個指向字串的指標,它用來接受從檔案讀出的文本,以”/0”結束。

nMax是本次所允許讀入的文本字元個數,不計“/0”字元,也就是說最多能讀入nMax-1個文本字元。

ReadString的傳回值是一個LPTSTR類型的指標,它指向從檔案讀出的文本字串,如果到達檔案尾,則返回NULL。

ReadString的另一種形式為:

BOOL ReadString(CString& rString);

參數rString用來容納從檔案讀出的文本。

CString版本忽略斷行符號分行符號,傳回值是一個布爾值。如果傳回值為FALSE,表示因到達檔案尾而沒有讀到任何字元。

提示:每執行一次ReadString,就會自動從文字檔中讀取一行資料,同時檔案操作指標會自動跳轉到下一行。 執行個體3:從檔案中讀取文本資訊

步驟:建立基於對話方塊的MFC程式,刪除所有自動添加的控制項,添加按鈕控制項,為按鈕添加事件,並在相應的函數處,添加如下代碼:

char* pszFileName="C://myfile.txt";CStdioFile myFile;CFileException fileException;if(myFile.Open(pszFileName,CFile::typeText|CFile::modeReadWrite),&fileException){    myFile.SeekToBegin();    CString str1;    myFile.ReadString(str1);    CString str2;    myFile.ReadString(str2);    AfxMessageBox(str1+str2);}else{    TRACE("Can't open file %s,error=%u/n",pszFileName,fileException.m_cause);}myFile.Close();

程式運行結果:為程式F9設定斷點,然後F5逐步執行,結果如下:

5.關閉檔案

對檔案的操作完成後,使用CloseFile關閉檔案。

函數CStdioFile::Close關閉一個檔案,一般一個檔案使用完畢就應該關閉它:

myFile.Close();
錯誤的文字檔讀寫過程

在讀寫文字檔的時候,最常見的錯誤是---操作檔案不存在。這種錯誤產生的典型原因有: 1.路徑錯誤

char * pszFileName="C://Windows//MyFile.txt";CStdioFile myFile;CFileException fileException;if(!myFile.Open(pszFileName,CFile::modeCreate|CFile::typeText|CFile::modeReadWrite),&fileException){    //檔案作業碼}else{    TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause);}myFile.Close();

由於將檔案變數與一個絕對路徑的檔案名稱關聯,而程式的資料通常儲存在相對路徑下,所以一旦相對路徑和相對路徑不一致時,就會出錯。

舉例而言,上一段程式本意是想從windows的安裝目錄下面的MyTextFile.txt檔案中讀取一行資料,但是如果作業系統安裝的路徑不是C:/Windwos,而是C:/Winnt,那麼這段程式就會出錯。

解決方案是在程式中使用相對路徑,改正後的程式如下:

//擷取windows路徑LPTSTR lpBuffer=new char[MAX_PATH];::GetWindowsDirectory(lpBuffer,MAX_PATH);strcat(lpBuffer,"//MyFile.txt");CStdioFile myFile;CFileException fileException;if(myFile.Open(lpBuffer,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException){    //檔案作業碼}else{    TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause);}CString strFileTitle="MyFile.txt";CStdioFile myFile;CFileException fileException;if(myFile.Open(strFileTitle,CFile::typeText|CFile::modeReadWrite),&fileException){    //檔案作業碼    myFile.WriteString("測試。");}else{    TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause);}myFile.Close();
2.操作檔案不存在

如果應用程式所有路徑下面不存在MyFile.txt檔案,那麼在WriteString寫入資訊時就會出錯。

解決辦法就是在程式中開啟檔案前要檢查是否存在此檔案。如下程式:

CString strFileTitle="MyFile.txt";CFileFind finder;if(finder.FindFile(strFileTitle)){    CStdioFile myFile;    CFileException fileException;    if(myFile.Open(lpBuffer,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException)    {        //檔案作業碼    }    else    {        TRACE("Can't open file %s, error = %u/n",pszFileName,fileException.m_cause);    }}else{    TRACE("Can't find file %s/n",strFileTitle);}myFile.Close();
3.超越檔案許可權進行讀寫操作

在開啟檔案的過程中,通過參數指定了檔案的讀寫權限,如果讀寫的操作沒有和相應的許可權對應,就會出現錯誤。

下面的程式就是典型的忽略了檔案操作許可權的例子:

CString strFileTitle="MyFile.txt";CStdioFile myFile;CFileException fileException;if(myFile.Open(strFileTitle,CFile::typeText|CFile::modeCreate|CFile::NoTruncate|CFile::modeRead),&fileException){    //檔案作業碼    myFile.WriteString("測試!");}else{    TRACE("Can't open file %s,error=%u/n",strFileTitle,fileException.m_cause);}myFile.Close();
支招兒: 1.準確定位檔案的路徑

操作檔案的過程中,經常需要將文字檔放在程式自身的目錄中,但是如果僅僅在程式中使用不指定任何路徑資訊的相對路徑,如:

myFile.Open("MyFile.txt",CFile::modeCreate|CFile::typeText|CFile::modeReadWrite);

那麼就有可能出現不能正確定位的情況,準確定位檔案位置的方法是獲得可執行程式自身的絕對路徑,如:

TCHAR FilePath[MAX_PATH];GetModuleFileName(NULL,FilePath,MAX_PATH);(_tcstchr(FilePath,'//'))[1]=0;lstrcat(FilePath,_T("MyFile.txt"));CStdioFile myFile;CFileException fileException;if(myFile.Open(FilePath,CFile::modeCreate|CFile::typeText|CFile::modeReadWrite),&fileException){    //檔案作業碼}else{    TRACE("Can't open file %s,error=%u/n",FilePath,fileException.m_cause);}myFile.Close();
2.讀文字檔指定的一行,並得到文字檔的總行數。

讀文字檔指定的一行,並得到文字檔的總行數

要統計文字檔的總行數,可以從頭逐行讀,直到檔案尾,程式:

CStdioFile myFile;CFileException fileException;if(myFile.Open("MyFile.txt",CFile::modeCreate|CFile::modeNoTruncate|CFile::typeText|CFile::modeReadWrite),&fileException){    CString strContent;    int order=1;    while(myFile.ReadString(strContent))    {        if(2==order)        {            AfxMessageBox(strContent);        }        order=order+1;    }}else{    TRACE("Can't open file");}myFile.Close();
執行個體示範檔案操作過程 客戶操作記錄執行個體

本軟體分為兩個部分,一部分是DLL模組,裡面利用Hook技術完成鍵盤監控和寫入檔案的功能;另一部分是介面部分,調用DLL啟動和停止客戶操作記錄功能。

第1步:建立MFC DLL項目

第2步:建立TestHook.h檔案

第3步:加入全域共用資料變數

第4步:儲存DLL執行個體控制代碼

第5步:類CKeyboradHook的成員函數

第6步:建立鉤子可執行程式 第1步:建立MFC DLL項目

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.