CFile
//創建/打開文件 CFile file; file.Open(_T("test.txt"),CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite);//文件打開模式可組合使用,用“|”隔開,常用的有以下幾種: //CFile::modeCreate:以新建方式打開,如果文件不存在,新建;如果文件已存在,把該文件長度置零,即清除文件原有內容。 //CFile::modeNoTruncate:以追加方式打開,如果文件存在,打開并且不將文件長度置零,如果文件不存在,會拋出異常。一般與//CFile::modeCreate一起使用,則文件不存在時,新建一個文件;存在就進行追加操作。 //CFile::modeReadWrite:以讀寫方式打開文件。 //CFile::modeRead:只讀。 //CFile::modeWrite:只寫。//寫入數據 CString strValue = "Hello World!"; file.Write(strValue,strValue.GetLength());//追加數據 file.SeekToEnd(); //將指針移至文件末尾進行追加 file.Write(strValue,strValue.GetLength());//關閉文件 file.Close();
?
CStdioFile
CStdioFile是CFile的派生類,對文件進行流式操作,對于文本文件的讀寫很有用處,可按行讀取寫入。
//寫入數據 CString strValue = "Hello World!"; file.WriteString(strValue);//讀取數據 CString strRead; file.ReadString(strRead);//當文件存在多行數據需要逐行讀取時,可用函數BOOL CStdioFile::ReadString(CString& rString),當遇到"\n "時讀取截斷,如果文件未讀完,返回true,否則返回false。//逐行讀取文件內容,存入strRead while(file.ReadString(strRead)) {...; }
?
各種關于文件的操作在程序設計中是十分常見,如果能對其各種操作都了如指掌,就可以根據實際情況找到最佳的解決方案,從而在較短的時間內編寫出高效的代碼,因而熟練的掌握文件操作是十分重要的。本文將對Visual C++中有關文件操作進行全面的介紹,并對在文件操作中經常遇到的一些疑難問題進行詳細的分析。
1.文件的查找
當對一個文件操作時,如果不知道該文件是否存在,就要首先進行查找。MFC中有一個專門用來進行文件查找的類CFileFind,使用它可以方便快捷地進行文件的查找。下面這段代碼演示了這個類的最基本使用方法。
CString strFileTitle;CFileFind finder;BOOL bWorking = finder.FindFile("C:\\windows\\sysbkup\\*.cab");while(bWorking){bWorking=finder.FindNextFile();strFileTitle=finder.GetFileTitle();}
?
2.文件的打開/保存對話框
讓用戶選擇文件進行打開和存儲操作時,就要用到文件打開/保存對話框。MFC的類CFileDialog用于實現這種功能。使用CFileDialog聲明一個對象時,第一個BOOL型參數用于指定文件的打開或保存,當為TRUE時將構造一個文件打開對話框,為FALSE時構造一個文件保存對話框。
在構造CFileDialog對象時,如果在參數中指定了OFN_ALLOWMULTISELECT風格,則在此對話框中可以進行多選操作。此時要重點注意為此CFileDialog對象的m_ofn.lpstrFile分配一塊內存,用于存儲多選操作所返回的所有文件路徑名,如果不進行分配或分配的內存過小就會導致操作失敗。下面這段程序演示了文件打開對話框的使用方法。
CFileDialog mFileDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,"All Files (*.*)|*.*||",AfxGetMainWnd());CString str(" ",10000);mFileDlg.m_ofn.lpstrFile=str.GetBuffer(10000);str.ReleaseBuffer();POSITION mPos=mFileDlg.GetStartPosition();CString pathName(" ",128);CFileStatus status;while(mPos!=NULL){pathName=mFileDlg.GetNextPathName(mPos);CFile::GetStatus( pathName, status );}
?
3.文件的讀寫
文件的讀寫非常重要,下面將重點進行介紹。文件讀寫的最普通的方法是直接使用CFile進行,如文件的讀寫可以使用下面的方法:
//對文件進行讀操作char sRead[2];CFile mFile(_T("user.txt"),CFile::modeRead);if(mFile.GetLength()<2)return;mFile.Read(sRead,2);mFile.Close();//對文件進行寫操作CFile mFile(_T("user.txt "), CFile::modeWrite|CFile::modeCreate);mFile.Write(sRead,2);mFile.Flush(); (Forces any data remaining in the file buffer to be written to the file)mFile.Close();//雖然這種方法最為基本,但是它的使用繁瑣,而且功能非常簡單。我向你推薦的是使用CArchive,它的使用方法簡單且功能十分強大。首先還是用CFile聲明一個對象,然后用這個對象的指針做參數聲明一個CArchive對象,你就可以非常方便地存儲各種復雜的數據類型了。它的使用方法見下例。//對文件進行寫操作 CString strTemp;CFile mFile;mFile.Open("d:\\dd\\try.TRY",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);CArchive ar(&mFile,CArchive::store);ar<< ar.Close();mFile.Close();//對文件進行讀操作 CFile mFile;if(mFile.Open("d:\\dd\\try.TRY",CFile::modeRead)==0)return;CArchive ar(&mFile,CArchive::load);ar>>strTemp;ar.Close();mFile.Close();//CArchive的 << 和>> 操作符用于簡單數據類型的讀寫,對于CObject派生類的對象的存取要使用ReadObject()和WriteObject()。使用CArchive的ReadClass()和WriteClass()還可以進行類的讀寫,如://存儲CAboutDlg類 ar.WriteClass(RUNTIME_CLASS(CAboutDlg));//讀取CAboutDlg類CRuntimeClass* mRunClass=ar.ReadClass();//使用CAboutDlg類CObject* pObject=mRunClass->CreateObject();((CDialog* )pObject)->DoModal();
雖然VC提供的文檔/視結構中的文檔也可進行這些操作,但是不容易理解、使用和管理,因此雖然很多VC入門的書上花費大量篇幅講述文檔/視結構,但我建議你最好不要使用它的文檔。關于如何進行文檔/視的分離有很多書介紹,包括非常著名的《Visual C++ 技術內幕》。
如果你要進行的文件操作只是簡單的讀寫整行的字符串,我建議你使用CStdioFile,用它來進行此類操作非常方便,如下例。
CStdioFile mFile;CFileException mExcept;mFile.Open( "d:\\temp\\aa.bat", CFile::modeWrite, &mExcept);CString string="I am a string.";mFile.WriteString(string);mFile.Close();
?
4.臨時文件的使用
正規軟件經常用到臨時文件,你經常可以會看到C:\Windows\Temp目錄下有大量的擴展名為tmp的文件,這些就是程序運行是建立的臨時文件。臨時文件的使用方法基本與常規文件一樣,只是文件名應該調用函數GetTempFileName()獲得。它的第一個參數是建立此臨時文件的路徑,第二個參數是建立臨時文件名的前綴,第四個參數用于得到建立的臨時文件名。得到此臨時文件名以后,你就可以用它來建立并操作文件了,如:
char szTempPath[_MAX_PATH],szTempfile[_MAX_PATH];GetTempPath(_MAX_PATH, szTempPath);GetTempFileName(szTempPath,_T ("my_"),0,szTempfile);CFile m_tempFile(szTempfile,CFile:: modeCreate|CFile:: modeWrite);char m_char='a';m_tempFile.Write(&m_char,2);m_tempFile.Close();
?
5.文件的復制、刪除等
MFC中沒有提供直接進行這些操作的功能,因而要使用SDK。SDK中的文件相關函數常用的有CopyFile()、CreateDirectory()、DeleteFile()、MoveFile()。它們的用法很簡單,可參考MSDN。
1,判斷文件是否存在
?? ??access(filename,mode);
2,對于不同用途又不同的文件操作,其中API函數CreateFile()也是比較有用處理方式,對于巨型文件很合適。其他的樓上的大都說了,不重復了.
//[1]顯示對話框,取得文件名 CString FilePathName; CFileDialog dlg(TRUE);///TRUE為OPEN對話框,FALSE為S***E AS對話框 if (dlg.DoModal() == IDOK)FilePathName=dlg.GetPathName();//相關信息:CFileDialog 用于取文件名的幾個成員函數: //假如選擇的文件是C:\WINDOWS\TEST.EXE則
//(1)GetPathName();取文件名全稱,包括完整路徑。取回C:\WINDOWS\TEST.EXE //(2)GetFileTitle();取文件全名:TEST.EXE //(3)GetFileName();取回TEST //(4)GetFileExt();取擴展名EXE//[2]打開文件 CFile file("C:\HELLO.TXT",CFile::modeRead);//只讀方式打開 //CFile::modeRead可改為 CFile::modeWrite(只寫), //CFile::modeReadWrite(讀寫),CFile::modeCreate(新建) //例子: { CFile file; file.Open("C:\HELLO.TXT",CFile::modeCreate|Cfile::modeWrite); . . . }//[3]移動文件指針 file.Seek(100,CFile::begin);///從文件頭開始往下移動100字節 file.Seek(-50,CFile::end);///從文件末尾往上移動50字節 file.Seek(-30,CFile::current);///從當前位置往上移動30字節 file.SeekToBegin();///移到文件頭 file.SeekToEnd();///移到文件尾//[4]讀寫文件 //讀文件: char buffer[1000]; file.Read(buffer,1000); //寫文件: CString string("自強不息"); file.Write(string,8);//[5]關閉文件 file.Close();
CFile Read函數與CStdioFile的ReadString函數比較,Read 函數可以讀取指定大小的字符串,ReadString可以讀取到換行符前的所有字符串,而File函數的fgetc()也可以讀取,但一次只能得到一個字節
FILE ,其與CFILE 有點相似.示例如下
char datain[101];FILE *fp_sys;//打開數據文件fp_sys = fopen("要打開的文件名", "rb");//第二個參數為打開方法,r代表讀,b代表二進制方式if(fp_sys == NULL) {AfxMessageBox("無法打開文件");return FALSE;}//讀取數據文件fread(datain, sizeof(unsigned char ), 42, fp_sys);//參數說明:第一個是接收的變量,第二個是類型的內存大小,第三個是字數的數量,第四個是讀的文件//寫出數據到文件 fwrite(output_data, sizeof(unsigned char ), 40, fp_out););//參數說明:第一個是要寫出的變量,第二個是類型的內存大小,第三個是字數的數量,第四個是寫的文件
?
?
CStdioFile類學習筆記
CStdioFile類繼承自CFile類,CStdioFile對象表示一個用運行時的函數fopen打開的c運行時的流式文件。流式文件是被緩沖的,而且可以以文本方式(默認)或者二進制方式打開。
CStdioFile類不支持CFile類中的Duplicate、LockRange、UnlockRange函數,如果你使用了,會得到CNotSupportedException類的錯誤。
CStringFile類默認的是按照Text模式操作文件。CFile?類默認的是按照二進制模式操作文件。
這里大致說明一下二進制模式和Text模式的區別。
二進制模式:對于一行的結尾我們必須輸入”\r\n”,才能表示回車換行的效果。
Text 模式 :”\r”回車的工作是自動完成的,我們只需要寫入”\n”即可。所以我們再使用文本模式時要主要,當我們從外部讀入文件時,”\r\n”會被翻譯成”\n”,寫入文件時,我們對于回車換行只需提供”\n”,即可,”\r\n”會被寫入到文件中。
?
構造函數:
CStdioFile(); CStdioFile(FILE *pOpenStream); CStdioFile(LPCTSTR lpFileName, UINT nOpenFlags); throw(CFileException); FILE *pOpenStream:指的是c運行函數fopen調用后返回的文件指針。 LPCTSTR lpFileName:指的是被打開的文件(絕對地址或相對地址) UINT nOpenFlags:指的是CFile類中所描述的打開文件的方式。virtual LPTSTR ReadString(LPTSTR lpsz, UINT nMax); throw(CFileException); 如果使用該函數讀取文本文件,當遇到”\r\n”,停止讀取,并去掉”\r”,保留”\n”,并在字符串尾部增加”\0”,nMax的長度包含有”\0”字符, 實際的分析如下: 如果nMax <= 字符數,讀取(nMax-1)個字符+0x00; 如果nMax = 字符數 + 1,讀取nMax個字符+0x00; 如果nMax > 字符數,讀取nMax個字符+0x0A(”\n”) + 0x00; 如果文件有多行,則當文件沒有讀完時,返回NOT NULL,讀到文件尾,返回NULL。BOOL ReadString(CString& rString); throw(CFileException); 讀取一行文本到rString中,遇到回車換行符停止讀取,回車和換行符均不讀到rString中,尾部也不添加”0x00”。 如果文件有多行,則當文件沒有讀完時,返回TRUE,讀到文件尾,返回FALSE。virtual void WriteString(LPTSTR lpsz); throw(CFileException); 將緩沖區中的數據寫入到與CStdioFile對象相關聯的文件中,不支持CString類型數據寫入,結束的”\0”不被寫入到文件中,lpsz緩沖區中的所有換行符被替換為回車換行符即”\n”轉換為”\r\n”。
?