[WinAPI] API 10 [創建、打開、讀寫文件,獲取文件大小]


 

 

在Windows系統中,創建和打開文件都是使用API函數CreateFile,CreateFile通過指定不同的參數來表示是新建一個文件,打開已經存在的文件,還是重新建立文件等。讀寫文件最為直接的方式是使用ReadFile和WriteFile函數,也可以使用文件鏡像,獲取文件大小一般使用GetFileSize函數,也可以使用GetFileAttributesEx等函數(在上節介紹)。讀寫文件、獲取文件大小之前都需要使用CreateFile創建或打開的文件,獲得文件句柄。
在文件操作中,文件句柄是一個關鍵的概念。文件句柄惟一標識了一個文件,ReadFile、WriteFile、GetFileSize等函數是使用文件句柄作為參數來表示,用戶需要讀、寫、獲取大小的文件是哪一個文件。在對文件進行操作前,都必須要使用CreateFile獲得文件句柄。

 

(1)CreateFile
CreateFile是文件操作中最主要的一個函數。幾乎所有的文件操作都需要使用到文件句柄。而CreateFile函數為這些操作建立文件句柄。CreateFile函數的參數多,而且比較復雜,涉及文件名、文件的共享模式、存取方式、操作模式、權限、標志和文件屬性等。每一個參數都可以有多種值可供選擇,代表了不同的意義。

◇參數
lpFileName:輸入參數,操作對象文件的相對路徑或絕對路徑。
dwDesiredAccess:輸入參數,指明對文件對象的操作存取方式,可以是GENERIC_READ,表示需要讀文件;可以是GENERIC_WRITE,表示需要寫文件;也可以是GENERIC_READGENERIC_WRITE,表示既可以讀也可以寫。
dwShareMode:輸入參數,共享模式。指明與其他進程是否共享該文件,可以是共享讀(FILE_SHARE DELETE)、共享寫(FILE_SHARE_WRITE)、共享刪除(FILE_SHARE.READ),如果要指明多個屬性,使用“位與~‘I”運算。如果指明上述參數,其他進程就可以對文件進行相關操作。如果本進程需要獨占本文件,則將本參數設置為0。
lpSecurityAttributes:指向SECURITY_ATTRIBUTES結構的指針,表示本文件句柄的安全屬性,能影響其是否可被子進程繼承等操作。如果設定為NULL,則子進程不可繼承本句柄。SECURITY ATTRIBUTES結構不常用,對此數據結構的設置,涉及Windows系統中對權限管理的原理,在本章中不作詳細說明。
dwCreationDisposition:輸入參數,操作模式。

dwFlagsAndAttributes:輸入參數,文件屬性和文件標志

一般情況下文件屬性較常用,而操作標志不常用,可以使用“1”運算符指定多個屬性和標志。
hTemplateFile:輸入參數,當存取權限包括GENERIC_WRITE時,可以設置為一個模板文件的句柄。一般情況下,可設置為NULL,表示不使用模板文件。
◇返回值
返回HANDLE數據類型值,表示文件的句柄,如果返回INVALID_HANDLE_VALUE,表示操作失敗。

 

(2)ReadFile。
ReadFile動能是從文件中讀出數據。需要使用CreateFile所返回的文件句柄。

◇參數
hFile:輸入參數,讀取數據的文件對象,由CreateFile創建,調用CreateFile打開文件時需要指明GENERIC_READ讀取操作模式。
lpBuffer:輸入參數,指向讀取文件數據存儲的內存緩沖區。
nNumberOfBytesToRead:輸入參數,指明需要從文件中讀出的數據的大小,不能大於lpBuffer內存塊的大小,否則會造成溢出。
lpNumberOfBytesRead:輸出參數,指向存儲實際讀出的數據大小的DWORD變量。在讀文件時,可能由於已經到達文件尾等原因,其值可能小於rtNumberOfBytesToRead。如果lpOverlapped為NULL,則該參數不能為NULL。
lpOverlapped:輸入參數,指向OVERLAPPED結構體的指針,如果調用CreateFile時設置了FILE_FLAG_OVERLAPPED標志,則需要使用該參數,否則可以為NULL。
◇返回值
返回BOOL值,表示讀文件是否成功。
◇使用說明
在讀的過程中,文件指針會隨着讀操作的進行而自動移動,在循環調用本函數時,會順序讀出文件的內容,如果程序返回失敗,可以使用GetLastError函數獲取錯誤信息。

 

(3)WriteFile。
WriteFile函數的功能是將數據寫入到文件中,寫入到文件指針所在的位置,寫入操作完成后,文件指針會移動到寫入的數據之后

◇參數
hFile:輸入參數,寫入數據的文件對象,由CreateFile創建,調用CreateFile打開文件時,需要指明GENERIC_WRITE讀取操作模式。
lpBuffer:輸入參數,指向需寫入文件數據存儲的內存緩沖區。
nNumberOBytesToWrite:輸入參數,指明需要寫入文件中的數據的大小。
lpNumberOiBytesWritten:輸出參數,指向存儲真實寫入的數據大小的變量,可能由於已經到達文件尾等原因,其值可能與nNumberOfBytesToWrite不同。如果lpOverlapped為NULL,則該參數不能為NULL。
lpOverlapped:輸入參數,指向OVERLAPPED結構體的指針,如果調用CreateFile時設置了FILE_FLAG_OVERIAPPED標志,則需要使用該參數。可以為NULL。
◇返回值
返回BOOL值,表示寫文件是否成功。
◇使用說明

在讀的過程中,文件指針會隨着寫操作的進行而移動,在循環調用本函數時,會按順序寫入文件內容。如果程序返回失敗,可以使用 GetLastError函數獲取錯誤信息。

 

(4)GetFileSize、GetFileSizeEX.
GetFileSize、GetFileSizeEX的功能是一致的,都是獲取文件大小

◇參數
GetFileSize的參數如下。
hFile:輸入參數,讀取數據的文件對象,由CreateFile創建,調用CreateFile打開文件時需要指明GENERIC_READ讀取操作模式或者GENERIC_WRITE寫入操作模式。
lpFileSizeHigh:輸出參數,表示得到的文件大小的高32位。該參數可以為NULL,為NULL時表示文件大小可以用DWORD表示。具體解釋請參考返回值部分。
GetFileSizeEx的參數如下。
hFile:輸入參數,讀取數據的文件對象,由CreateFile創建,調用CreateFile打開文件時,需要指明GENERIC_READ讀取操作模式或者GENERIC_WRITE寫入操作模式。
lpFileSize:輸出參數,指向儲存文件大小的一個LARGE_ INTEGER聯合體,前面已經介紹過了LARGE.1NTEGER結構的相關內容,參見API 9 小節關鍵數據結構部分。
◇返回值
GetFileSize成功時,返回值為一個表示文件大小DWORD值。
GetFileSize失敗時,如果lpFileSizeHigh為NULL,返回INVALID_ FILE_SIZE並可以調用GetLastError函數獲取更詳細的錯誤信息;如果lpFileSizeHigh為非NULL,那么同樣返回INVALID_FILE_SIZE並且嘗試讀取lpFileSizeHigh指向的值放在高32位,並將其和返回的低32位DWORD連起來成為一個64位的值來表示文件大小。lpFileSizeHigh為合法值則GetLastError返回NO_ERROR,表示該API仍然成功;否則,GetLastError返回一個不等於NO_ERROR的值。

GetFileSizeEx直接返回BOOL值,表示讀文件是否成功。

◇使用說明
實際上這兩個函數的區別就在於,對文件大小超出DWORD的情況采取不同處理方式。由於歷史原因,GetFileSize用兩個32位值來分別儲存64位文件大小的高位和地位;而GetFileSizeEx直接將文件大小儲存在64位的聯合體中。

 

>>>本實例使用CreateFile、ReadFile、WriteFile來完成創建、打開、讀寫文件的功能。筆者在實例中自己編寫一個SaveDataToFile函數在D盤根目錄下建立一個show.txt並向文件中寫入數據,並編寫了一個ReadFileContent函數讀取文件的內容。

 

 

  1 #include <Windows.h>
  2 #include <stdio.h>
  3 
  4 DWORD ReadFileContent(LPSTR szFilePath)
  5 {
  6     //文件大小
  7     HANDLE hFileRead;
  8     //保存文件大小
  9     LARGE_INTEGER liFileSize;
 10     //成功讀取的文件數據大小
 11     DWORD dwReadedSize;
 12     //累加計算已經讀取的數據的大小
 13     LONGLONG liTotalRead=0;
 14     //文件數據緩存
 15     BYTE lpFileDataBuffer[32];
 16 
 17     //打開已經存在的文件,讀取內容
 18     hFileRead = CreateFileA(szFilePath,//name
 19         GENERIC_READ,                   //以讀方式打開
 20         FILE_SHARE_READ,               //可共享讀
 21         NULL,                           //默認安全設置
 22         OPEN_EXISTING,                   //只打開已經存在的文件
 23         FILE_ATTRIBUTE_NORMAL,           //常規文件屬性
 24         NULL);                           //無模板
 25     //打開文件是否成功
 26     if(hFileRead==INVALID_HANDLE_VALUE)
 27     {
 28         printf("打開文件失敗: %d",GetLastError());
 29     }
 30     if(!GetFileSizeEx(hFileRead,&liFileSize))
 31     {
 32         printf("獲取文件大小失敗: %d",GetLastError());
 33     }
 34     else
 35     {
 36         printf("文件大小為: %d\n",liFileSize.QuadPart);
 37     }
 38     //循環讀取並打印內容
 39     while(TRUE)
 40     {
 41         DWORD i;
 42         if(!ReadFile(hFileRead,//讀取文件句柄
 43             lpFileDataBuffer,  //存儲讀取文件內容
 44             32,                   //讀取的大小(字節)
 45             &dwReadedSize,       //實際讀取的大小
 46             NULL))               //不使用Overlapped
 47         {
 48             printf("讀取文件錯誤: %d\n",GetLastError());
 49             break;
 50         }
 51         printf("讀取了%d字節,文件內容是: ",dwReadedSize);
 52 
 53         for(i=0;i<dwReadedSize;i++)
 54         {
 55             printf("0x%x ",lpFileDataBuffer[i]);
 56         }
 57         printf("\n");
 58         liTotalRead+=dwReadedSize;
 59         if(liTotalRead==liFileSize.QuadPart)
 60         {
 61             printf("讀取文件結束\n");
 62             break;
 63         }
 64     }
 65     CloseHandle(hFileRead);
 66     return 0;
 67 }
 68 
 69 DWORD SaveDataToFile(
 70     LPSTR szFilePath,
 71     LPVOID lpData,
 72     DWORD dwDataSize)
 73 {
 74     //文件句柄
 75     HANDLE hFileWrite;
 76     //成功寫入的數據大小
 77     DWORD dwWritedDateSize;
 78     //打開已經存在的文件,讀取內容
 79     hFileWrite=CreateFileA(szFilePath,//要打開的文件名
 80         GENERIC_WRITE,//以寫方式打開開
 81         0,//可共享讀
 82         NULL,//默認安全設置
 83         OPEN_ALWAYS,//打開已經存在的文件
 84         FILE_ATTRIBUTE_NORMAL,//常規屬性打開
 85         NULL);//無模板
 86     //判斷是否成功打開
 87     if(hFileWrite==INVALID_HANDLE_VALUE)
 88     {
 89         printf("打開文件失敗: %d\n",GetLastError());
 90     }
 91     //設置文件指針到文件為
 92     SetFilePointer(hFileWrite,0,0,FILE_END);
 93     //將數據寫入文件
 94     if(!WriteFile(hFileWrite,lpData,dwDataSize,&dwWritedDateSize,NULL))
 95     {
 96         printf("寫文件失敗: %d\n",GetLastError());
 97     }
 98     else
 99     {
100         printf("寫文件成功,寫入%d字節。\n",dwWritedDateSize);
101     }
102     CloseHandle(hFileWrite);
103     return 0;
104 }
105 int main()
106 {
107     LPSTR szFileData="這是一個例子";
108     SaveDataToFile("D:\\show.txt",szFileData,lstrlenA(szFileData));
109     ReadFileContent("D:\\show.txt");
110     return 0;
111 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM