国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

萬網(wǎng)域名申請網(wǎng)站全自動推廣引流軟件

萬網(wǎng)域名申請網(wǎng)站,全自動推廣引流軟件,哪個網(wǎng)站企業(yè)郵箱最好,盤古網(wǎng)站建設(shè)怎么樣文件的輸入輸出(I/O)服務(wù)是操作系統(tǒng)的重要部分。Windows提供了一類API函數(shù)來讀、寫和管理磁盤文件。MFC將這些函數(shù)轉(zhuǎn)化為一個面向?qū)ο蟮念悺狢File,它允許將文件視為可以由CFile成員函數(shù)操作的對象,如Read和Write等。CFile類實(shí)現(xiàn)…

文件的輸入輸出(I/O)服務(wù)是操作系統(tǒng)的重要部分。Windows提供了一類API函數(shù)來讀、寫和管理磁盤文件。MFC將這些函數(shù)轉(zhuǎn)化為一個面向?qū)ο蟮念悺狢File,它允許將文件視為可以由CFile成員函數(shù)操作的對象,如Read和Write等。CFile類實(shí)現(xiàn)了程序開發(fā)者執(zhí)行底層文件I/O需要的大部分功能。

并不是在任何時(shí)候使用CFile類都是方便的,特別是要與底層設(shè)備(如COM口、設(shè)備驅(qū)動)進(jìn)行交互的時(shí)候,所以本節(jié)主要討論管理文件的API函數(shù)。事實(shí)上,了解這些函數(shù)之后,自然就會使用CFile類了。

8.1.1 創(chuàng)建和讀寫文件

使用API函數(shù)讀寫文件時(shí),首先要使用CreateFile函數(shù)創(chuàng)建文件對象(即打開文件),調(diào)用成功會返回文件句柄;然后以此句柄為參數(shù)調(diào)用ReadFile和WriteFile函數(shù),進(jìn)行實(shí)際的讀寫操作;最后調(diào)用CloseHandle函數(shù)關(guān)閉不再使用的文件對象句柄。

1.打開和關(guān)閉文件
CreateFile是一個功能相當(dāng)強(qiáng)大的函數(shù),Windows下的底層設(shè)備差不多都是由它打開的。它可以創(chuàng)建或打開文件、目錄、物理磁盤、控制臺緩沖區(qū)、郵槽和管道等。調(diào)用成功后,函數(shù)返回能夠用來訪問此對象的句柄,其原型如下。

HANDLE CreateFile (  LPCTSTR lpFileName,   // 要創(chuàng)建或打開的對象的名稱  DWORD dwDesiredAccess,  // 文件的存取方式  DWORD dwShareMode,  // 共享屬性 LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全屬性  DWORD dwCreationDisposition, // 文件存在或不存在時(shí)系統(tǒng)采取的行動  DWORD dwFlagsAndAttributes, // 新文件的屬性  HANDLE hTemplateFile // 一個文件模板的句柄 
); 

各參數(shù)含義如下。
(1)lpFileName參數(shù)是要創(chuàng)建或打開的對象的名稱。如果打開文件,直接在這里指定文件名稱即可;如果操作對象是第一個串口,則要指定“COM1”為文件名,然后就可以像操作文件一樣操作串口了;如果要打開本地電腦上的一個服務(wù),要以“"\\.\服務(wù)名稱"”為文件名,其中的“.”代表本地機(jī)器;也可以使用CreateFile打開網(wǎng)絡(luò)中其他主機(jī)上的文件,此時(shí)的文件名應(yīng)該是“\\主機(jī)名\共享目錄名\文件名”。
(2)dwDesiredAcces參數(shù)是訪問方式,它指定了要對打開的對象進(jìn)行何種操作。指定GENERIC_READ標(biāo)志表示以只讀方式打開;指定GENERIC_WRITE標(biāo)志表示以只寫方式打開;指定這兩個值的組合,表示要同時(shí)對打開的對象進(jìn)行讀寫操作。
(3)dwShareMode參數(shù)指定了文件對象的共享模式,表示文件打開后是否允許其他代碼以某種方式再次打開這個文件,它可以是下列值的一個組合:

0                   不允許文件再被打開 C語言中的fopen函數(shù)就是這樣打開文件的 
FILE_SHARE_DELETE   允許以后的程序代碼對文件刪除文件(Win98系列的系統(tǒng)不支持這 個標(biāo)志) 
FILE_SHARE_READ     允許以后的程序代碼以讀方式打開文件
FILE_SHARE_WRITE    允許以后的程序代碼以寫方式打開文件

(4)dwCreationDisposition參數(shù)指定了當(dāng)文件已存在或者不存在時(shí)系統(tǒng)采取的動作。在這里設(shè)置不同的標(biāo)志就可以決定究竟是要打開文件,還是要創(chuàng)建文件。參數(shù)的可能取值如下:

CREATE_ALWAYS       創(chuàng)建新文件。如果文件存在,函數(shù)會覆蓋這個文件,清除存在的屬性 
CREATE_NEW          創(chuàng)建新文件。如果文件存在,函數(shù)執(zhí)行失敗 
OPEN_ALWAYS         如果文件已經(jīng)存在,就打開它,不存在則創(chuàng)建新文件 
OPEN_EXISTING       打開存在的文件。如果文件不存在,函數(shù)執(zhí)行失敗 
TRUNCATE_EXISTING   打開文件并將文件截?cái)酁榱?#xff0c;當(dāng)文件不存在時(shí)函數(shù)執(zhí)行失敗 

(5)dwFlagsAndAttributes參數(shù)用來指定新建文件的屬性和標(biāo)志。文件屬性可以是下面這些值的組合:

FILE_ATTRIBUTE_ARCHIVE    標(biāo)記歸檔屬性 
FILE_ATTRIBUTE_HIDDEN     標(biāo)記隱藏屬性
FILE_ATTRIBUTE_READONLY   標(biāo)記只讀屬性 
FILE_ATTRIBUTE_READONLY   標(biāo)記系統(tǒng)屬性
FILE_ATTRIBUTE_TEMPORARY  臨時(shí)文件。操作系統(tǒng)會盡量把所有文件的內(nèi)容保持在內(nèi) 存中以加快存取速度。使用完后要盡快將它刪除

此參數(shù)還可同時(shí)指定對文件的操作方式,下面是一些比較常用的方式:

FILE_FLAG_DELETE_ON_CLOSE  文件關(guān)閉后系統(tǒng)立即自動將它刪除
FILE_FLAG_OVERLAPPED       使用異步讀寫文件的方式 
FILE_FLAG_WRITE_THROUGH    系統(tǒng)不會對文件使用緩存,文件的任何改變都會被系統(tǒng) 立即寫入硬盤

(6)hTemplateFile參數(shù)指定了一個文件模板句柄。系統(tǒng)會復(fù)制該文件模板的所有屬性到當(dāng)前創(chuàng)建的文件中。Windows 98系列的操作系統(tǒng)不支持它,必須設(shè)為NULL。

打開或創(chuàng)建文件成功時(shí),函數(shù)返回文件句柄,失敗時(shí)返回INVALID_HANDLE_VALUE(-1)。如果想再詳細(xì)了解失敗的原因,可以繼續(xù)調(diào)用GetLastError函數(shù)。

用不同的參數(shù)組合調(diào)用CreateFile函數(shù)可以完成不同的功能,例如,下面的代碼為讀取數(shù)據(jù)打開了一個存在的文件。

HANDLE hFile;  
hFile = CreateFile("myfile.txt", // 要創(chuàng)建的文件  GENERIC_WRITE, // 要寫這個文件  0, // 不共享  NULL, // 默認(rèn)安全屬性  CREATE_ALWAYS, // 如果存在就覆蓋  FILE_ATTRIBUTE_NORMAL, // 普通文件  NULL); // 沒有模板  if(hFile == INVALID_HANDLE_VALUE)  { ……// 不能夠打開文件 } 

要關(guān)閉打開的文件,直接以CreateFile返回的文件句柄調(diào)用CloseHandle函數(shù)即可。

2.移動文件指針
系統(tǒng)為每個打開的文件維護(hù)一個文件指針,指定對文件的下一個讀寫操作從什么位置開始。隨著數(shù)據(jù)的讀出或?qū)懭?#xff0c;文件指針也隨之移動。當(dāng)文件剛被打開時(shí),文件指針處于文件的頭部。有時(shí)候需要隨機(jī)讀取文件內(nèi)容,這就需要先調(diào)整文件指針,SetFilePointer函數(shù)提供了這個功能,原型如下。

DWORD SetFilePointer (  HANDLE hFile, // 文件句柄  LONG lDistanceToMove, // 要移動的距離  PLONG lpDistanceToMoveHigh, // 移動距離的高32位,一般設(shè)置為NULL  DWORD dwMoveMethod // 移動的模式  
); 

dwMoveMethod參數(shù)指明了從什么地方開始移動,可以是下面的一個值:

FILE_BEGIN    開始移動位置為0,即從文件頭部開始移動
FILE_CURRENT  開始移動位置是文件指針的當(dāng)前值 
FILE_END      開始移動位置是文件的結(jié)尾,即從文件尾開始移動

函數(shù)執(zhí)行失敗返回-1,否則返回新的文件指針的位置。

文件指針也可以移動到所有數(shù)據(jù)的后面,比如現(xiàn)在文件的長度是100 KB,但還是可以成功的將文件指針移動到1000 KB的位置。這樣做可以達(dá)到擴(kuò)展文件長度的目的。

SetEndOfFile函數(shù)可以截?cái)嗷蛘邤U(kuò)展文件。該函數(shù)移動指定文件的結(jié)束標(biāo)志(end-of-file,EOF)到文件指針指向的位置。如果文件擴(kuò)展,舊的EOF位置和新的EOF位置間的內(nèi)容是未定義的。SetEndOfFile函數(shù)的用法如下。

BOOL SetEndOfFile(HANDLE hFile); 

截?cái)嗷蛘邤U(kuò)展文件時(shí),要首先調(diào)用SetFilePointer移動文件指針,然后再調(diào)用SetFilePointer函數(shù)設(shè)置新的文件指針位置為EOF。

3.讀寫文件
讀寫文件的函數(shù)是ReadFile和WriteFile,這兩個函數(shù)既可以同步讀寫文件,又可以異步讀寫文件。而函數(shù)ReadFileEx和WriteFileEx只能異步讀寫文件。

從文件讀取數(shù)據(jù)的函數(shù)是ReadFile,向文件寫入數(shù)據(jù)的函數(shù)是WriteFile,操作的開始位置由文件指針指定。這兩個函數(shù)的原型如下。

BOOL ReadFile(  
HANDLE hFile, // 文件句柄  
LPVOID lpBuffer, // 指向一個緩沖區(qū),函數(shù)會將讀出的數(shù)據(jù)返回到這里  
DWORD nNumberOfBytesToRead, // 要求讀入的字節(jié)數(shù)  
LPDWORD lpNumberOfBytesRead, // 指向一個DWORD類型的變量,  // 用于返回實(shí)際讀入的字節(jié)數(shù)  
LPOVERLAPPED lpOverlapped // 以便設(shè)為NULL 
); 
BOOL WriteFile (hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); 

當(dāng)用WriteFile寫文件時(shí),寫入的數(shù)據(jù)通常被Windows暫時(shí)保存在內(nèi)部的高速緩存中,等合適的時(shí)候再一并寫入磁盤。如果一定要保證所有的數(shù)據(jù)都已經(jīng)被傳送,可以強(qiáng)制使用FlushFileBuffers函數(shù)來清空數(shù)據(jù)緩沖區(qū),函數(shù)的惟一參數(shù)是要操作的文件句柄。

BOOL FlushFileBuffers (HANDLE hFile ); 

4.鎖定文件
當(dāng)對文件數(shù)據(jù)的一致性要求較高時(shí),為了防止程序在寫入的過程中其他進(jìn)程剛好在讀取寫入?yún)^(qū)域的內(nèi)容,可以對已打開文件的某個部分進(jìn)行加鎖,這就可以防止其他進(jìn)程對該區(qū)域進(jìn)行讀寫。加鎖和解鎖的函數(shù)是LockFile和UnlockFile,它們的原形如下。

BOOL LockFile(  HANDLE hFile, // 文件句柄  DWORD dwFileOffsetLow, // 加鎖的開始位置  DWORD dwFileOffsetHigh,  DWORD nNumberOfBytesToLockLow, // 加鎖的區(qū)域的大小  DWORD nNumberOfBytesToLockHigh  
); 
UnlockFile ( hFile, dwFileOffsetLow, dwFileOffsetHigh,  nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh); 

dwFileOffsetLow和dwFileOffsetHigh參數(shù)組合起來指定了加鎖區(qū)域的開始位置,nNumberOfBytesToLockLow和nNumberOfBytesToLockHigh參數(shù)組合起來指定了加鎖區(qū)域的大小。這兩個參數(shù)都指定了一個64位的值,在Win32中,只使用32位就夠了。

如果加鎖文件的進(jìn)程終止,或者文件關(guān)閉時(shí)還未解鎖,操作系統(tǒng)會自動解除對文件的鎖定。但是,操作系統(tǒng)解鎖文件花費(fèi)的時(shí)間取決于當(dāng)前可用的系統(tǒng)資源。因此,進(jìn)程終止時(shí)最好顯式地解鎖所有已鎖定的文件,以免造成這些文件無法訪問。

8.1.2 獲取文件信息

1.獲取文件類型
Windows下的許多對象都稱之為文件,如果想知道一個文件句柄究竟對應(yīng)什么對象,可以使用GetFileType函數(shù),原型如下。

DWORD GetFileType(HANDLE hFile); 

函數(shù)的返回值說明了文件類型,可以是下面的一個值:

FILE_TYPE_CHAR     指定文件是字符文件,通常是LPT設(shè)備或控制臺 
FILE_TYPE_DISK     指定文件是磁盤文件 
FILE_TYPE_PIPE     指定文件是套節(jié)字,一個命名的或未命名的管道 
FILE_TYPE_UNKNOWN  不能識別指定文件,或者函數(shù)調(diào)用失敗 

2.獲取文件大小
如果確定操作的對象是磁盤文件,還可以使用GetFileSize函數(shù)取得這個文件的長度。

DWORD GetFileSize(  HANDLE hFile, // 文件句柄  LPDWORD lpFileSizeHigh // 用于返回文件長度的高字。可以指定這個參數(shù)為NULL 
); 

函數(shù)執(zhí)行成功將返回文件大小的低雙字,如果lpFileSizeHigh參數(shù)不是NULL,函數(shù)將文件大小的高雙字放入它指向的DWORD變量中。

如果函數(shù)執(zhí)行失敗,并且lpFileSizeHigh是NULL,返回值將是INVALID_FILE_SIZE;如果函數(shù)執(zhí)行失敗,但lpFileSizeHigh不是NULL,返回值是INVALID_FILE_SIZE,進(jìn)一步調(diào)用GetLastError會返回不為NO_ERROR的值。

如果返回值是INVALID_FILE_SIZE,應(yīng)用程序必須調(diào)用GetLastError來確定函數(shù)調(diào)用是否成功。原因是,當(dāng)lpFileSizeHigh不為NULL或者文件大小為0xffffffff時(shí),函數(shù)雖然調(diào)用成功了,但依然會返回INVALID_FILE_SIZE。這種情況下,GetLastError會返回NO_ERROR來響應(yīng)成功。

3.獲取文件屬性
如果要查看文件或者目錄的屬性,可以使用GetFileAttributes函數(shù),它會返回一系列FAT風(fēng)格的屬性信息。

DWORD GetFileAttributes(LPCTSTR lpFileName); // lpFileName指定了文件或者目錄的名稱 

函數(shù)執(zhí)行成功,返回值包含了指定文件或目錄的屬性信息,可以是下列取值的組合:

FILE_ATTRIBUTE_ARCHIVE     文件包含歸檔屬性 
FILE_ATTRIBUTE_COMPRESSED  文件和目錄被壓縮 
FILE_ATTRIBUTE_DIRECTORY   這是一個目錄 
FILE_ATTRIBUTE_HIDDEN      文件包含隱含屬性
FILE_ATTRIBUTE_NORMAL      文件沒有其他屬性 
FILE_ATTRIBUTE_READONLY    文件包含只讀屬性
FILE_ATTRIBUTE_SYSTEM      文件包含系統(tǒng)屬性
FILE_ATTRIBUTE_TEMPORARYT  文件是一個臨時(shí)文件 

這些屬性對目錄也同樣適用。INVALID_FILE_ATTRIBUTES(0xFFFFFFFF)是函數(shù)執(zhí)行失敗后的返回值。

下面是快速檢查某個文件或目錄是否存在的自定義函數(shù),可以將它用在自己的工程中。

BOOL FileExists(LPCTSTR lpszFileName, BOOL bIsDirCheck) 
{ // 試圖取得文件的屬性  DWORD dwAttributes = GetFileAttributes(lpszFileName);  if(dwAttributes == 0xFFFFFFFF)  return FALSE;  if ((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)  { if (bIsDirCheck)  return TRUE; else  return FALSE;  }  else  { if (!bIsDirCheck)  return TRUE; else  return FALSE;  } 
} 

第2個參數(shù)bIsDirCheck指定要檢查的對象是目錄還是文件。

與GetFileAttributes相對應(yīng)的函數(shù)是SetFileAttributes,這個函數(shù)用來設(shè)置文件屬性。

BOOL SetFileAttributes(  LPCTSTR lpFileName, // 目標(biāo)文件名稱  DWORD dwFileAttributes // 要設(shè)置的屬性值 
); 

8.1.3 常用文件操作

1.拷貝文件
拷貝文件的函數(shù)是CopyFile和CopyFileEx,其作用都是復(fù)制一個存在的文件到一個新文件中。CopyFile函數(shù)的用法如下。

BOOL CopyFile(  LPCTSTR lpExistingFileName, // 指定已存在的文件的名稱  LPCTSTR lpNewFileName, // 指定新文件的名稱  BOOL bFailIfExists // 如果指定的新文件存在是否按出錯處理 
); 

CopyFileEx函數(shù)的附加功能是允許指定一個回調(diào)函數(shù),在拷貝過程中,函數(shù)每拷貝完一部分?jǐn)?shù)據(jù),就會調(diào)用回調(diào)函數(shù)。用戶在回調(diào)函數(shù)中可以指定是否停止拷貝,還可以顯示進(jìn)度條來指示拷貝的進(jìn)度。

2.刪除文件
刪除文件的函數(shù)是DeleteFile,僅有的參數(shù)是要刪除文件的名稱。

BOOL DeleteFile(LPCTSTR lpFileName); 

如果應(yīng)用程序試圖刪除不存在的文件,DeleteFile將執(zhí)行失敗。如果目標(biāo)文件是只讀的,函數(shù)也會執(zhí)行失敗,出錯代碼為ERROR_ACCESS_DENIED。為了刪除只讀文件,先要去掉其只讀屬性。

DeleteFile函數(shù)可以標(biāo)識一個文件為“關(guān)閉時(shí)刪除”。因此,直到最后一個到此文件的句柄關(guān)閉之后,文件才會被刪除。

下面的自定義函數(shù)RecursiveDelete示例了如何刪除指定目錄下的所有文件和子目錄。

void RecursiveDelete(CString szPath) 
{ CFileFind ff; // MFC將查找文件的API封裝到了CFileFind類 讀者可參考下面的框架使用這個類  CString strPath = szPath;  // 說明要查找此目錄下的所有文件  if(strPath.Right(1) != "\\")  strPath += "\\"; strPath += "*.*";  BOOL bRet;  if(ff.FindFile(strPath))  { do  { bRet = ff.FindNextFile();  if(ff.IsDots()) // 目錄為“.”或者“..”?  continue;  strPath = ff.GetFilePath();  if(!ff.IsDirectory())  { // 刪除此文件  ::SetFileAttributes(strPath, FILE_ATTRIBUTE_NORMAL);  ::DeleteFile(strPath);  }   else  { // 遞歸調(diào)用  RecursiveDelete(strPath);  // 刪除此目錄(RemoveDirectory只能刪除空目錄)  ::SetFileAttributes(strPath, FILE_ATTRIBUTE_NORMAL);  ::RemoveDirectory(strPath);  }  }  while(bRet);  } 
} 

用DeleteFile函數(shù)刪除的文件不會被放到回收站,它們將永遠(yuǎn)丟失,所以請小心使用RecursiveDelete函數(shù)。

3.移動文件
移動文件的函數(shù)是MoveFile和MoveFileEx函數(shù)。它們的主要功能都是用來移動一個存在的文件或目錄。MoveFile函數(shù)用法如下。

BOOL MoveFile(  LPCTSTR lpExistingFileName, // 存在的文件或目錄  LPCTSTR lpNewFileName // 新的文件或目錄 
); 

當(dāng)需要指定如何移動文件時(shí),請使用MoveFileEx函數(shù)。

BOOL MoveFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags);

dwFlags參數(shù)可以是下列值的組合:

MOVEFILE_DELAY_UNTIL_REBOOT   函數(shù)并不馬上執(zhí)行,而是在操作系統(tǒng)下一此重新啟動時(shí)才移動文件。在AUTOCHK執(zhí)行之后,系統(tǒng)立即移動文件,這是在創(chuàng)建任何分頁文件之前進(jìn)行的。因此,這個值使函數(shù)能夠刪除上一次運(yùn)行時(shí)使用的分頁文件。只有擁有管理員權(quán)限的用戶才可以使用這個值 
MOVEFILE_REPLACE_EXISTING     如果目標(biāo)文件已存在的話,就將它替換掉
MOVEFILE_WRITE_THROUGH        直到文件實(shí)際從磁盤移除之后函數(shù)才返回 

如果指定了MOVEFILE_DELAY_UNTIL_REBOOT標(biāo)記,lpNewFileName參數(shù)可以指定為NULL,這種情況下,當(dāng)系統(tǒng)下一次啟動時(shí),操作系統(tǒng)會刪除lpExistingFileName參數(shù)指定的文件。

8.1.4 檢查PE文件有效性的例子

PE文件格式是任何可執(zhí)行模塊或者DLL的文件格式,PE文件以64字節(jié)的DOS文件頭(IMAGE_DOS_HEADER結(jié)構(gòu))開始,之后是一小段DOS程序,然后是248字節(jié)的NT文件頭(IMAGE_NT_HEADERS結(jié)構(gòu))。NT文件頭的偏移地址由IMAGE_DOS_HEADER結(jié)構(gòu)的e_lfanew成員給出。

檢查文件是不是有效PE文件的一個方法是檢查IMAGE_DOS_HEADER和IMAGE_NT_HEADERS結(jié)構(gòu)是否有效。IMAGE_DOS_HEADER結(jié)構(gòu)定義如下。

typedef struct _IMAGE_DOS_HEADER 
{  WORD e_magic; // DOS可執(zhí)行文件標(biāo)記,為“MZ”。依此識別DOS頭是否有效  ... // 其他成員,沒什么用途  LONG e_lfanew; // IMAGE_NT_HEADERS結(jié)構(gòu)的地址  
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; 

IMAGE_NT_HEADERS結(jié)構(gòu)定義如下。

typedef struct _IMAGE_NT_HEADERS 
{  DWORD Signature; // PE文件標(biāo)識,為“PE\0\0”。依此識別NT文件頭是否有效  IMAGE_FILE_HEADER FileHeader;  IMAGE_OPTIONAL_HEADER OptionalHeader;  
} IMAGE_NT_HEADERS, 

為了編程方便,Windows為DOS文件標(biāo)記和PE文件標(biāo)記都定義了宏標(biāo)識。

#define IMAGE_DOS_SIGNATURE   0x5A4D // MZ 
#define IMAGE_NT_SIGNATURE    0x00004550 // PE00 

檢查文件是否為PE文件的步驟如下:
(1)檢驗(yàn)文件頭部第一個字的值是否等于IMAGE_DOS_SIGNATURE,是則說明DOS MZ頭有效。
(2)一旦證明文件的DOS頭有效后,就可用e_lfanew來定位PE頭了。
(3)比較PE頭的第一個字是否等于IMAGE_NT_SIGNATURE。如果這個值也匹配,那么就認(rèn)為該文件是一個有效的PE文件。

下面是驗(yàn)證PE文件有效性的代碼,在配套光盤的08ValidPE工程下。

// ValidPE.cpp文件#include <afxdlgs.h>
#include "ValidPE.h"CMyApp theApp;BOOL CMyApp::InitInstance()
{// 彈出選色文件對話框CFileDialog dlg(TRUE);if(dlg.DoModal() != IDOK)return FALSE;// 打開檢查的文件HANDLE hFile = ::CreateFile(dlg.GetFileName(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if(hFile == INVALID_HANDLE_VALUE){MessageBox(NULL, "無效文件!", "ValidPE", MB_OK);}// 定義PE文件中的DOS頭和NT頭IMAGE_DOS_HEADER dosHeader;IMAGE_NT_HEADERS32 ntHeader;	// 驗(yàn)證過程BOOL bValid = FALSE;DWORD dwRead;// 讀取DOS頭::ReadFile(hFile, &dosHeader, sizeof(dosHeader), &dwRead, NULL);if(dwRead == sizeof(dosHeader)){if(dosHeader.e_magic == IMAGE_DOS_SIGNATURE) // 是不是有效的DOS頭?{// 定位NT頭if(::SetFilePointer(hFile, dosHeader.e_lfanew, NULL, FILE_BEGIN) != -1){// 讀取NT頭::ReadFile(hFile, &ntHeader, sizeof(ntHeader), &dwRead, NULL);if(dwRead == sizeof(ntHeader)){if(ntHeader.Signature == IMAGE_NT_SIGNATURE)	// 是不是有效的NT頭bValid = TRUE;}}}}// 顯示結(jié)果if(bValid)MessageBox(NULL, "是一個PE格式的文件!", "ValidPE", MB_OK);elseMessageBox(NULL, "不是一個PE格式的文件!", "ValidPE", MB_OK);::CloseHandle(hFile);return FALSE;
}

在這里插入圖片描述
上述代碼簡單明確,先利用Windows定義的宏IMAGE_DOS_SIGNATURE判斷DOS頭,比較DOS頭的e_magic字段;再通過DOS頭的e_lfanew字段定位到NT頭;最后檢查NT頭的Signature字段是不是IMAGE_NT_SIGNATURE(即“PE\0\0”)。

8.1.5 MFC的支持(CFile類)

CFile是一個相當(dāng)簡單的封裝了一部分文件I/O處理函數(shù)的類。它的成員函數(shù)用于打開和關(guān)閉文件、讀寫文件數(shù)據(jù)、刪除和重命名文件、取得文件信息。它的公開成員變量m_hFile保存了與CFile對象關(guān)聯(lián)的文件的文件句柄。一個受保護(hù)的CString類型的成員變量m_strFileName保存了文件的名稱。成員函數(shù)GetFilePath、GetFileName和GetFileTitle能夠用來提取整個或者部分文件名。比如,如果完整的文件名是“C:\MyWork\File.txt”,GetFilePath返回整個字符串,GetFileName返回“File.txt”,GetFileTitle返回“File”。

但是詳述這些函數(shù)就會忽略CFile類的特色,這就是用來寫數(shù)據(jù)到磁盤和從磁盤讀數(shù)據(jù)的函數(shù)。下面簡單介紹CFile類用法。

**1.打開和創(chuàng)建文件 **
使用CFile類打開文件有兩種方法。

(1)構(gòu)造一個未初始化的CFile對象,調(diào)用CFile::Open函數(shù)。下面的部分代碼使用這個技術(shù)以讀寫權(quán)限打開一個名稱為File.txt的文件。

CFile file; 
if(file.Open(_T ("File.txt"), CFile::modeReadWrite)) 
{ // 打開文件成功
}

CFile::Open函數(shù)的返回值是BOOL類型的變量。如果打開文件出錯,還想進(jìn)一步了解出錯的原因,可以創(chuàng)建一個CFileException對象,傳遞它的地址到Open函數(shù)的第3個參數(shù)。

CFile file; 
CFileException e; 
if (file.Open(_T ("File.txt"), CFile::modeReadWrite, &e)) 
{ // 打開文件成功
} 
else 
{ // 打開文件失敗,告訴用戶原因  e.ReportError(); 
} 

如果打開失敗,CFile::Open函數(shù)會使用描述失敗原因的信息初始化一個CFileException對象。ReportError成員函數(shù)基于這個信息顯示一個出錯對話框??梢酝ㄟ^檢查CFileException類的公有成員m_cause找到導(dǎo)致這個錯誤的原因。

(2)使用CFile類的構(gòu)造函數(shù)??梢詫?chuàng)建文件對象和打開文件合并成一步,如下面代碼所示。

CFile file(_T ("File.txt"), CFile::modeReadWrite); 

如果文件不能被打開,CFile的構(gòu)造函數(shù)會拋出一個CFileException異常。因此,使用CFile::CFile函數(shù)打開文件的代碼通常使用try和catch塊來捕獲錯誤。

try 
{ CFile file(_T ("File.txt"), CFile::modeReadWrite); 
} 
catch(CFileException* e) 
{ // 出錯了!  e->ReportError();  e->Delete(); 
} 

刪除MFC拋出的異常是程序?qū)懽髡叩呢?zé)任,所以在程序中處理完異常之后要調(diào)用異常對象的Delete函數(shù)。

為了創(chuàng)建一個文件而不是打開一個存在的文件,要在CFile::Open或者CFile構(gòu)造函數(shù)的第二個參數(shù)中包含上CFile::modeCreate標(biāo)記,如下代碼所示。

CFile file(_T("File.txt"), CFile::modeReadWrite | CFile::modeCreate); 

如果以這種方式創(chuàng)建的文件存在,它的長度會被截為0。為了在文件不存在時(shí)創(chuàng)建它,存在的時(shí)候僅打開而不截去,應(yīng)再包含上CFile::modeNoTruncate標(biāo)記,如下面代碼所示。

CFile file(_T("File.txt"), CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate); 

默認(rèn)情況下,由CFile::Open或CFile::CFile打開的文件使用的是獨(dú)占模式,即CreateFile API中的第3個參數(shù)dwShareMode被設(shè)為了0。如果需要,在打開文件時(shí)也可以指定一個共享模式,以明確同意其他訪問此文件的操作。這里是4個可以選擇的共享模式:

CFile::shareDenyNone   不獨(dú)占這個文件 
CFile::shareDenyRead   拒絕其他代碼對這個文件進(jìn)行讀操作 
CFile::shareDenyWrite  拒絕其他代碼對這個文件進(jìn)行寫操作
CFile::shareExclusive  拒絕其他代碼對這個文件進(jìn)行讀和寫操作(默認(rèn))

另外,還可以指定下面3個對象訪問類型中的一個:

CFile::modeReadWrite  請求讀寫訪問 
CFile::modeRead       僅請求讀訪問 
CFile::modeWrite      僅請求寫訪問 

常用的做法是允許其他程序以只讀方式打開文件,但是拒絕它們寫入數(shù)據(jù)。

CFile file(_T("File.txt"), CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate); 

如果在上面的代碼執(zhí)行之前,文件已經(jīng)以可寫的方式打開了,這個調(diào)用將會失敗,CFile類會拋出CFileException異常,異常對象的m_cause成員等于CFileException::sharingViolation。

CFile類的成員函數(shù)Close會調(diào)用CloseHandle API關(guān)閉應(yīng)用程序打開的文件對象句柄。如果句柄沒有關(guān)閉,類的析構(gòu)函數(shù)也會調(diào)用Close函數(shù)關(guān)閉它。顯式調(diào)用Close函數(shù)一般都是為了關(guān)閉當(dāng)前打開的文件,以便使用同樣的CFile對象打開另一個文件。

2.讀寫文件
CFile類中從文件中讀取數(shù)據(jù)的成員函數(shù)是Read。例如,下面的代碼申請了一塊4KB大小的文件I/O緩沖區(qū),每次從文件讀取4KB大小的數(shù)據(jù)。

BYTE buffer[4096]; 
CFile file (_T("File.txt"), CFile::modeRead); 
DWORD dwBytesRemaining = file.GetLength(); 
while(dwBytesRemaining) 
{ UINT nBytesRead = file.Read(buffer, sizeof(buffer));  dwBytesRemaining -= nBytesRead; 
} 

文件中未讀取的字節(jié)數(shù)保存在dwBytesRemaining變量里,此變量由CFile::GetLength返回的文件長度初始化。每次調(diào)用Read之后,從文件中讀取的字節(jié)數(shù)(nBytesRead)會從dwBytesRemaining變量里減去。直到dwBytesRemaining為0整個while循環(huán)才結(jié)束。

CFile類還提供了Write成員函數(shù)向文件寫入數(shù)據(jù),Seek成員函數(shù)移動文件指針,它們都和相關(guān)API一一對應(yīng)。可以通過跟蹤程序的執(zhí)行來查看這些函數(shù)的實(shí)現(xiàn)代碼。

http://aloenet.com.cn/news/34497.html

相關(guān)文章:

  • 網(wǎng)站上的logo怎么做今日國內(nèi)新聞
  • 網(wǎng)站設(shè)計(jì)聯(lián)盟西安seo學(xué)院
  • 網(wǎng)站開發(fā)wbs工作分解結(jié)構(gòu)北京互聯(lián)網(wǎng)公司有哪些
  • wordpress背景圖更改網(wǎng)站自然優(yōu)化
  • 北京網(wǎng)站如何制作seo網(wǎng)站關(guān)鍵詞優(yōu)化快速官網(wǎng)
  • wordpress 入侵視頻優(yōu)化營商環(huán)境條例全文
  • 怎么設(shè)計(jì)app太原seo排名外包
  • 做app好還是響應(yīng)式網(wǎng)站深圳企業(yè)黃頁網(wǎng)
  • 萊蕪營銷型網(wǎng)站制作廣東省各城市疫情搜索高峰進(jìn)度
  • 網(wǎng)絡(luò)營銷案例分析200字關(guān)鍵詞seo如何優(yōu)化
  • 網(wǎng)站整體運(yùn)營思路互聯(lián)網(wǎng)推廣引流
  • 中國招標(biāo)投標(biāo)網(wǎng)查詢平臺站長之家 seo查詢
  • 網(wǎng)站輪播廣告代碼怎樣搭建一個網(wǎng)站
  • 無錫 網(wǎng)站建設(shè)公司廣州做seo整站優(yōu)化公司
  • 榆林市網(wǎng)站建設(shè)網(wǎng)站開發(fā)工具
  • 深圳專業(yè)網(wǎng)站制作費(fèi)用怎么建一個自己的網(wǎng)站
  • 政務(wù)公開政府網(wǎng)站建設(shè)管理百度刷搜索詞
  • wordpress 首頁調(diào)用頁面標(biāo)題城關(guān)網(wǎng)站seo
  • 廣州 網(wǎng)站建設(shè)網(wǎng)絡(luò)推廣網(wǎng)頁設(shè)計(jì)免費(fèi)推廣廣告鏈接
  • 學(xué)校網(wǎng)站推廣seo關(guān)鍵詞排名優(yōu)化怎樣
  • 國外炫酷網(wǎng)站外貿(mào)平臺app
  • 網(wǎng)業(yè)端云服務(wù)武漢seo網(wǎng)站排名優(yōu)化
  • 減肥網(wǎng)站源碼seo需求
  • 國內(nèi)最好的crm軟件南昌seo技術(shù)外包
  • 個人備案網(wǎng)站做企業(yè)網(wǎng)可以嗎北京搜索引擎優(yōu)化主管
  • 網(wǎng)站專題建設(shè)合同2024新聞熱點(diǎn)事件
  • wordpress布置網(wǎng)站教程友情鏈接只有鏈接
  • seo搜索引擎優(yōu)化技術(shù)教程關(guān)鍵詞排名優(yōu)化提升培訓(xùn)
  • 網(wǎng)站信息資料庫建設(shè)品牌seo是什么
  • 什么專業(yè)的會做網(wǎng)站網(wǎng)站統(tǒng)計(jì)