MFC中文件的建立
在操作系統中,文件是放在一定的目錄下,在創建以及操作文件以前,我們要查看文件要保存的目錄有沒有存在,如果不存在要創建。這就要用到GetFileAttributes()和CreateDirectory()兩個函數。下面是這兩個函數的簡介:
1、GetFileAttributes
函數原型:
DWORD WINAPI GetFileAttributes( __in LPCTSTR lpFileName );
函數參數
lpFileName [in] :文件或目錄的名字,對於ANSI版本,名字不能大於MAX_PATH。
函數返回值
如果函數成功,返回值包含文件或目錄的屬性。如果函數失敗,返回值是INVALID_FILE_ATTRIBUTES。
在MSDN中,文件總共有15種屬性,根據磁盤的分區格式不同,文件的屬性也會不同。現在針對GetFileAttributes 函數的返回值做以下整理:
返回字段
返回值
屬性類型
FILE_ATTRIBUTE_READONLY
1
只讀
FILE_ATTRIBUTE_HIDDEN
2
隱藏
FILE_ATTRIBUTE_SYSTEM
4
系統
FILE_ATTRIBUTE_DIRECTORY
16
目錄
FILE_ATTRIBUTE_ARCHIVE
32
存檔
FILE_ATTRIBUTE_DEVICE
64
保留
FILE_ATTRIBUTE_NORMAL
128
正常
FILE_ATTRIBUTE_TEMPORARY
256
臨時
FILE_ATTRIBUTE_SPARSE_FILE
512
稀疏文件
FILE_ATTRIBUTE_REPARSE_POINT
1024
超鏈接或快捷方式
FILE_ATTRIBUTE_COMPRESSED
2048
壓縮
FILE_ATTRIBUTE_OFFLINE
4096
脫機
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
8192
索引
FILE_ATTRIBUTE_ENCRYPTED
16384
加密
FILE_ATTRIBUTE_VIRTUAL
65536
虛擬
橙色標記的屬性爲Windows系統中文件的公有屬性,其中“只讀”、“隱藏”、“系統”、“存檔”爲文件的四種基本屬性。compressed,content_indexed,encrypted只存在於NTFS分區中。
文件去掉全部屬性後(四種基本屬性),將自動標記爲normal。同時具有system和hidden屬性的文件會在系統中徹底隱形,這也是病毒常用的伎倆。
commpressed和encrypted不能共存。默認情況下文件都有content_indexed屬性
以上內容轉自:http://hi.baidu.com/li0544/item/5c6a4f0872c7ac18ebfe3856
2、CreateDirectory
函數原型
BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
第一個參數值爲文件夾名稱,第二個參數值爲安全屬性,一般設置爲NULL即可。如果正確創建,返回值爲1,如果沒有正常創建文件夾,則返回0。
特別的:該函數每次調用時都只能創建一級文件夾,即文件夾中不能再包含子文件夾。
當希望創建含有子文件夾的文件夾時,可以先使用該函數創建一級文件夾,然後再使用該函數在一級文件夾下創建子文件夾。如:
希望創建:d:\\TEST\\temp,
則:CString str = “d:\\TEST”;
CreateDirectory(str, NULL);
str = str + \\temp;
CreateDirectory(str, NULL);
綜合利用以上兩個函數的例子如下:
if (!(GetFileAttributes("DataBase")==FILE_ATTRIBUTE_DIRECTORY))
{
if (!CreateDirectory("DataBase",NULL))
{
AfxMessageBox("Make Dir Error");
}
}
接下來我們就要直接編寫文件並且直接對文件進行打開、關閉、讀、寫等操作。MFC把這些對文件的操作封裝到了一個叫做CFile的類中,使用這個類的對象能夠以更直接的方式來處理文件。
CFile是MFC文件類的基類,它直接提供非緩衝的二進制磁盤輸入/輸出設備,並直接地通過派生類支持文本文件和內存文件。
使用CFILE類必須包含 #include <afx.h>
通常,CFILE類的構造過程中會自動打開磁盤文件,在析構函數中則會自動關閉文件。你可以使用靜態成員函數來詢問文件的狀態而不用打開文件。
在MFC裏面,打開一個文件最常用的方法分爲以下兩步:
1.創建一個用於打開文件的對象,通常都是聲明一個CFile或者一個CFile派生類的對象。
2.調用該CFile對象的Open方法,並提供一個文件路徑和打開方式作爲Open方法的參數。
下面就Cfile類封裝的函數進行介紹
1、CFile::Open
Open函數的原型如下:
virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL );
返回值:成功爲非0,否則爲0,僅當返回值爲0時pError參數纔有意義
參數:
lpszFileName 需要打開文件的路徑字符串,這個路徑可以是相對路徑也可以是絕對路徑,或者是網絡名字(UNC)
nOpenFlags 一個UINT定義文件的存取共享模式。它指定文件打開時可以採取的操作。你可以使用”|"號來組合多個選項。文件的一個存取權限和一個共享選項是必須要指定的。而modeCreate 和modeNoInherit是可選的。
具體如下:
CFile::modeCreate 讓構造器創建一個新文件,如果那個文件已經存在,把那個文件的長度重設爲
CFile::modeNoTruncate 可以同modeCreate. 一起用,如果要創建的文件已經存在,並不把它長度設置爲0,因而這個文件獲取或者作爲一個新建文件或者作爲一個已存在文件打開。這個功能往往很好用,比如說,當你需要打開一個設置文件,但是你並不清楚這個文件是否已經存在。
CFile::modeRead 打開文件僅僅供讀
CFile::modeReadWrite 打開文件供讀寫
CFile::modeWrite 打開文件只供寫
CFile::modeNoInherit 阻止這個文件被子進程繼承
CFile::shareDenyNone 打開這個文件同時允許其它進程讀寫這個文件。如果文件被其它進程以incompatibility模式打開,這是create操作會失敗。
CFile::shareDenyRead 打開文件拒絕其它任何進程讀這個文件。如果文件被其它進程用compatibility模式或者是讀方式打開,create操作失敗。
CFile::shareDenyWrite 打開文件拒絕其它任何進程寫這個文件。如果文件被其它進程用compatibility模式或者是寫方式打開,create操作失敗。
CFile::shareExclusive 以獨佔方式打開這個文件,不允許其它進程讀寫這個文件。 Construction fails if the file has been opened in any other mode for read or write access, even by the current process.
CFile::shareCompat 這個標誌在32位的MFC中無效。 This flag maps to CFile::shareExclusive when used in CFile::Open.
CFile::typeText 設置成對回車換行對有特殊處理的文本模式(僅用在派生類中)
CFile::typeBinary 設置二進制模式(僅用在派生類中)
pError-------一個指向一個已經存在的file-exception類的指針,它會接收文件失敗操作的具體狀態。
註明:
OPEN默認是用在CFILE的構造器中,這兩個函數提供了一個對文件的安全訪問方式,即使發生了錯誤也會正確的回報錯誤。
以上內容轉自http://blog.sina.com.cn/s/blog_673209640100i6pi.html
// example for CFile::Open
CFile f;
CFileException e;
char* pFileName = "test.dat";
if(!f.Open(pFileName, CFile::modeCreate | CFile::modeWrite,&e))
{
#ifdef _DEBUG
afxDump<<"File could not be opened"<<e.m_cause<<"\n";
#endif
}
注:CFileException類:
一個CFileException對象代表了與文件相關的異常。CFileException類包括有可移植的原因代碼和操作系統指定錯誤值等公共數據成員。此類也提供產生文件異常的靜態成員函數,返回操作系統和C運行中的錯誤原因代碼。
CFileException對象在CFile成員函數中被創建和產生,也可在派生類成員函數中創建或產生。可在CATCH表達式範圍內訪問這些對象。因爲可移植,可以僅用出錯代碼獲取異常的原因。
#include <afx.h>
CFileException類的成員
數據成員
m_cause |
包含異常原因相對應的可移植代碼 |
m_IosError |
包含相關操作系統錯誤代碼 |
m_strFileName |
包含異常的文件名 |
構造函數
構造一個CFileException對象 |
代碼轉換
OsErrorToException |
返回與操作系統錯誤值相對應的出錯原因代碼 |
ErrnoToException |
返回與運行錯誤值相對應的出錯原因代碼 |
幫助函數
ThrowOsError |
返回一個基於操作系統錯誤值相對應的出錯原因代碼 |
ThrowErrno |
產生一個基於運行錯誤值的文件異常 |
2、CFile::Read
函數原型
virtual UINT Read (void* lpBuf,UINT nCount);
返回值:
傳輸到緩衝區的字節數。注意對所有CFile類,如果到達文件尾,則返回值可能比nCount小。
參數: lpBuf 指向用戶提供的緩衝區以接收從文件中讀取的數據。 nCount 可以從文件中讀出的字節數的最大值。對文本模式的文件,回車換行作爲一個字符。
說明:從與CFile對象相關聯的文件讀數據到緩衝區。
示例:
// example for CFile::Read
extern CFile cfile;
char pbuf[100];
UINT nBytesRead = cfile.Read(pbuf,100);
3、CFile::Write
函數原型
virtual void Write(const void* lpBuf,UINT nCount);
throw (CFileException);
參數: lpBuf 指向用戶提供的緩衝區,包含將寫入文件中的數據。 nCount 從緩衝區內傳輸的字節數。對文本模式的文件,回車換行作爲一個字符。
說明:
將數據從緩衝區寫入與CFile對象相關聯的文件
示例:// example for CFile::Write
extern CFile cfile;
char pbuf[100];
cfile.Write(pbuf,100);
4、CFile::Seek
在打開的文件中重新定位一個指針。
函數原型
virtual LONG Seek(LONG lOff,UINT nFrom);
throw(CFileException);
返回值:如果要求的位置合法,則Seek返回從文件開始起的新字節偏移量。否則值未定義併產生CFileException異常。
參數: lOff 指針移動的字節數。 nFrom 指針移動的模式,可爲以下值之一:
CFile::begin 從文件開始,把指針向後移動lOff字節。
CFile::current 從當前位置開始,把指針向後移動lOff字節。
CFile::end 從文件尾開始,把指針向前移動lOff字節。注意必須移動到存在的文件中,因而lOff應爲負。如果爲正值,則超出文件尾。
示例:
// example for CFile::Seek
extern CFile cfile;
LONG lOffset = 1000;
LONG lActual = cfile.Seek(lOffset, CFile::begin);
5、CFile::SeekToBegin
函數原型:
void SeekToBegin( );
說明:
將文件指針指向文件開始處,等價於Seek(0L, CFile::begin)
示例:// example for CFile::SeekToBegin
extern CFile cfile;
cfile.SeekToBegin( );
6、CFile::SeekToEnd
函數原型:
DWORD SeekToEnd( );
返回值:文件長度(字節數)。
說明:
將文件指針指向文件邏輯尾部,等價於CFile::Seek( 0L, CFile::End);
示例:// example for CFile::SeekToEnd
extern CFile cfile;
DWORD dwActual = cfile.SeekToEnd( );
6、CFileFind類
CFileFind( );//構造函數。
virtual BOOL FindFile(LPCTSTR pstrName = NULL, DWORD dwUnused = 0);
參數: pstrName 指向待找文件名字符串,如果爲NULL,則查找以*.*形式進行。
dwUnused 保留,以使FindFile在派生類多形,必須爲0。
n virtual BOOL FindNextFile( );
返回值:如果還有文件,則返回非零值;如果爲最後一個文件,則爲0。
以下代碼將當前目錄下的文件枚舉出來並打印每個文件名:CFileFind finder
BOOL bWorking = finder.FindFile("*.*");
while(bWorking)
{
bWorking = finder.FindNextFile( );
cout <<(LPCTSTR) finder.GetFileName( ) <<endl;
}