天天看點

[Win32] 檔案系統操作

本文由CSDN使用者zuishikonghuan所作,轉載請注明出處: http://blog.csdn.net/zuishikonghuan/article/details/46963623

上一節講了檔案同步讀寫,這次就說說檔案系統的操作。

檔案系統,簡單了解一下,因為磁盤上資料有他的存儲方式,而應用程式如果對每種磁盤格式都有了解的話,無疑太難實作,而且相容性也無法保證,是以,作業系統就将具體的磁盤格式虛拟成(抽象成)一個檔案系統,應用程式隻需對檔案系統操作,磁盤裝置驅動程式會把對檔案系統的操作轉化為對磁盤扇區的操作,這就是檔案系統。

一。枚舉子目錄/枚舉檔案

依靠三個API實作: FindFirstFile、 FindNextFile、FindClose

MSDN:

FindFirstFile :https://msdn.microsoft.com/en-us/library/windows/desktop/aa364418(v=vs.85).aspx

HANDLE WINAPI FindFirstFile(
  _In_  LPCTSTR           lpFileName,
  _Out_ LPWIN32_FIND_DATA lpFindFileData
);
           

FindNextFile:https://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx

<pre class="cpp" name="code">BOOL WINAPI FindNextFile(
  _In_  HANDLE            hFindFile,
  _Out_ LPWIN32_FIND_DATA lpFindFileData
);
           

FindFirstFile:

lpFileName:目錄名稱,可以包含*和?,表示任意字元比如,我要枚舉D:\a\下面的所有檔案和目錄,就可以使用"D:\\a\\*.*"

lpFindFileData:指向一個WIN32_FIND_DATA結構的指針,用于接收檔案/目錄的資訊

傳回值:成功傳回搜尋句柄,失敗傳回INVALID_HANDLE_VALUE

FindNextFile:

hFindFile:以前調用 FindFirstFile 傳回的搜尋句柄

lpFindFileData:指向一個WIN32_FIND_DATA結構的指針,用于接收檔案/目錄的資訊

傳回值:成功傳回非0,失敗傳回0。沒有更多檔案時 GetLastError 傳回ERROR_NO_MORE_FILES

關于 WIN32_FIND_DATA結構:

typedef struct _WIN32_FIND_DATA {
  DWORD    dwFileAttributes;
  FILETIME ftCreationTime;
  FILETIME ftLastAccessTime;
  FILETIME ftLastWriteTime;
  DWORD    nFileSizeHigh;
  DWORD    nFileSizeLow;
  DWORD    dwReserved0;
  DWORD    dwReserved1;
  TCHAR    cFileName[MAX_PATH];
  TCHAR    cAlternateFileName[14];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;
           

dwFileAttributes:檔案屬性。下面有詳細解釋

ftCreationTime:檔案建立時間

ftLastAccessTime:上次通路時間

ftLastWriteTime:上次寫入時間

這三個時間都是 FILETIME 結構(以UTC計)

nFileSizeHigh:高位檔案大小,以位元組為機關。

檔案的大小等于 (nFileSizeHigh * (MAXDWORD + 1)) + nFileSizeLow。

nFileSizeLow:低位檔案大小,以位元組為機關。

dwReserved0:如果 dwFileAttributes 成員包括 FILE_ATTRIBUTE_REPARSE_POINT 屬性,該成員指定的重分析點标記。

否則為此值是未定義的并且不應使用。

dwReserved1:保留供将來使用。

cFileName:檔案名稱

cAlternateFileName:檔案的替代名稱。

此名稱是經典 8.3 檔案名格式。

例子:枚舉D盤下的檔案和目錄

#include <stdio.h>
#include <windows.h>


int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE find;
	WIN32_FIND_DATA data;
	find = FindFirstFile("D:\\*.*", &data);
	if (find == INVALID_HANDLE_VALUE){
		//出錯
		return 0;
	}
	do
	{
		//FILE_ATTRIBUTE_DIRECTORY會在下面說
		if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0){
			//檔案夾
			printf(data.cFileName);
			printf("  <DIR>\r\n");
		}
		else{
			//不是檔案夾,就是檔案
			puts(data.cFileName);
		}
	} while (FindNextFile(find, &data));
	getchar();
	return 0;
}
           

二。删除檔案

使用DeleteFile函數

MSDN:https://msdn.microsoft.com/en-us/library/windows/apps/aa363915(VS.85).aspx

函數原型:

<pre class="cpp" name="code">BOOL WINAPI DeleteFile(
  _In_ LPCTSTR lpFileName
);
           

lpFileName:檔案名稱

傳回值:成功傳回非0,失敗傳回0

三。判斷目錄

頭檔案: Shlwapi.h庫檔案:Shlwapi.lib

判斷檔案或目錄是否存在

PathFileExists(檔案或目錄名稱)存在傳回TRUE,不存在傳回FALSE

判斷目錄是否存在PathIsDirectory(目錄名稱字元串)是目錄傳回TRUE,不是傳回FALSE

判斷目錄是否為空目錄PathIsDirectoryEmpty(目錄名稱字元串)是空目錄傳回TRUE,不是空傳回FALSE

四。建立/删除目錄

建立目錄:CreateDirectory

MSDN:https://msdn.microsoft.com/en-us/library/windows/apps/aa363855(VS.85).aspx

函數原型:

BOOL WINAPI CreateDirectory(
  _In_     LPCTSTR               lpPathName,
  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
           

lpPathName:目錄名稱

lpSecurityAttributes:安全描述符,一般為NULL

注意不能一次建立多級目錄

傳回值:非0成功,0失敗

删除空目錄:RemoveDirectory

MSDN:https://msdn.microsoft.com/en-us/library/windows/apps/aa365488(VS.85).aspx

函數原型:

BOOL WINAPI RemoveDirectory(
  _In_ LPCTSTR lpPathName
);
           

lpPathName:目錄名稱

傳回值:非0成功,0失敗

五。讀取/設定檔案屬性

讀取:GetFileAttributes

MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/aa364944(v=vs.85).aspx

函數原型:

DWORD WINAPI GetFileAttributes(
  _In_ LPCTSTR lpFileName
);
           

lpFileName:檔案名稱

傳回值:成功傳回檔案屬性,失敗傳回INVALID_FILE_ATTRIBUTES

設定:SetFileAttributes

MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365535(v=vs.85).aspx

函數原型:

lpFileName:檔案名稱

dwFileAttributes:要設定的檔案屬性

傳回值:成功傳回非0,失敗傳回0

檔案屬性:(紅色為常用的)

FILE_ATTRIBUTE_ARCHIVE:檔案或目錄是一個存檔檔案或目錄。應用程式通常使用此屬性将檔案标記為備份或移除。

FILE_ATTRIBUTE_COMPRESSED:檔案或目錄被壓縮。對于檔案,所有檔案中的資料被壓縮。目錄,壓縮是新建立的檔案和子目錄的預設值。

FILE_ATTRIBUTE_DEVICE:此值被保留供系統使用。

FILE_ATTRIBUTE_DIRECTORY:辨別目錄的句柄。

FILE_ATTRIBUTE_ENCRYPTED:檔案或目錄加密的。對于檔案,檔案中的所有資料流進行都加密。目錄,加密是新建立的檔案和子目錄的預設值。

FILE_ATTRIBUTE_HIDDEN:隐藏的檔案或目錄。

FILE_ATTRIBUTE_INTEGRITY_STREAM:目錄或使用者資料流配置 (僅支援裁判的卷) 的完整性。它不是包括在普通目錄清單。完整性設定與檔案仍然存在,如果它被重命名。如果一個檔案被複制目标檔案将有完整性設定如果源的檔案或目标目錄設定的完整性。

Windows Server 2008 R2、 Windows 7、 Windows Server 2008,Windows Vista、 Windows Server 2003 和 Windows XP: 直到 Windows Server 2012 不支援此标志。

FILE_ATTRIBUTE_NORMAL:沒有其他檔案的屬性設定。此屬性是僅在單獨使用時有效。

FILE_ATTRIBUTE_NOT_CONTENT_INDEXED:檔案或目錄是不會通過内容索引服務索引。

FILE_ATTRIBUTE_NO_SCRUB_DATA:不能被了解的背景資料完整性掃描器 (AKA 洗滌器) 使用者資料流。當設定目錄上它隻提供繼承。此标志僅支援在存儲空間和裁判的卷上。它不是包括在普通目錄清單。

Windows Server 2008 R2、 Windows 7、 Windows Server 2008,Windows Vista、 Windows Server 2003 和 Windows XP: 直到 Windows 8 和 Windows Server 2012 不支援此标志。

FILE_ATTRIBUTE_OFFLINE:檔案的資料立即不是可用的。此屬性訓示檔案資料被實體地移動到脫機存儲區。此屬性使用遠端存儲,是分層存儲管理軟體。應用程式不應随意更改此屬性。

FILE_ATTRIBUTE_READONLY:是隻讀的檔案。應用程式可以讀取該檔案,但不能寫入或删除它。此屬性不用在目錄上。

FILE_ATTRIBUTE_REPARSE_POINT:檔案或目錄都有一個關聯的重分析點,或者是一個符号連結檔案。

FILE_ATTRIBUTE_SPARSE_FILE:是一個稀疏檔案的檔案。

FILE_ATTRIBUTE_SYSTEM:檔案或目錄的作業系統使用的一部分,或完全使用。

FILE_ATTRIBUTE_TEMPORARY:用于臨時存儲的檔案。檔案系統避免資料寫回到大容量存儲如果足夠的緩存記憶體不可用,因為通常情況下,應用程式會删除臨時檔案之後關閉句柄。在這種情況下,該系統可以完全避免寫入資料。否則,将資料寫入後關閉句柄。

FILE_ATTRIBUTE_VIRTUAL:此值被保留供系統使用。

六。複制檔案

1。CopyFile

MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851(v=vs.85).aspx

函數原型:

BOOL WINAPI CopyFile(
  _In_ LPCTSTR lpExistingFileName,
  _In_ LPCTSTR lpNewFileName,
  _In_ BOOL    bFailIfExists
);
           

lpExistingFileName:原檔案名

lpNewFileName:目标檔案名

bFailIfExists:如果此參數為 TRUE,指定的新檔案 lpNewFileName 已經存在,函數将失敗。如果此參數為 FALSE,并且新檔案已經存在,函數将覆寫現有的檔案并成功。

傳回值:成功傳回非0,失敗傳回0

2。CopyFileEx

MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/aa363852(v=vs.85).aspx

函數原型:

BOOL WINAPI CopyFileEx(
  _In_     LPCTSTR            lpExistingFileName,
  _In_     LPCTSTR            lpNewFileName,
  _In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine,
  _In_opt_ LPVOID             lpData,
  _In_opt_ LPBOOL             pbCancel,
  _In_     DWORD              dwCopyFlags
);
           

lpExistingFileName:原檔案名

lpNewFileName:目标檔案名

lpProgressRoutine:指向一個回調函數的指針,回調函數用于接收複制進度等資訊

lpData:要傳給回調函數的資料指針

pbCancel:如果此标志設定為 TRUE 時複制操作,則取消此操作。否則,複制操作将繼續完成。

dwCopyFlags:以下值:(紅色為常用的)

COPY_FILE_ALLOW_DECRYPTED_DESTINATION:嘗試将加密的檔案複制将成功即使目标副本不能加密。

COPY_FILE_COPY_SYMLINK:如果源檔案是一個符号連結,目标檔案也是指向相同源符号連結指向的檔案的符号連結。Windows Server 2003 和 Windows XP: 不支援此值。

COPY_FILE_FAIL_IF_EXISTS:如果目标檔案已存在,複制操作失敗。

COPY_FILE_NO_BUFFERING:使用無緩沖的 I/O,繞過系統 I/O 緩存資源執行複制操作。推薦用于非常大的檔案傳輸。

Windows Server 2003 和 Windows XP: 不支援此值。

COPY_FILE_OPEN_SOURCE_FOR_WRITE:複制檔案和原始檔案是為寫通路打開的。

COPY_FILE_RESTARTABLE:副本的追蹤其進展情況在目标檔案中複制發生故障的情況下。失敗的複制可以在以後重新啟動,通過指定相同的值為 lpExistingFileName 和 lpNewFileName 為那些失敗的調用中使用。這明顯可以減慢複制操作作為新的檔案可能在複制操作期間重新整理多次。

傳回值:成功傳回非0,失敗傳回0

關于回調函數:

DWORD CALLBACK CopyProgressRoutine(
  _In_     LARGE_INTEGER TotalFileSize,
  _In_     LARGE_INTEGER TotalBytesTransferred,
  _In_     LARGE_INTEGER StreamSize,
  _In_     LARGE_INTEGER StreamBytesTransferred,
  _In_     DWORD         dwStreamNumber,
  _In_     DWORD         dwCallbackReason,
  _In_     HANDLE        hSourceFile,
  _In_     HANDLE        hDestinationFile,
  _In_opt_ LPVOID        lpData
);
           

TotalFileSize:總檔案的大小,以位元組為機關。

TotalBytesTransferred:複制操作開始以來,從源檔案轉移到目标檔案的位元組總數。

StreamSize:以位元組為機關,目前的檔案流的總大小。

StreamBytesTransferred:目前流中的位元組數,複制操作開始以來,已從源檔案移交到目标檔案的總數。

dwStreamNumber:目前流的句柄。第一次調用 CopyProgressRoutine 時,流編号是 1。

dwCallbackReason:以下值之一

CALLBACK_CHUNK_FINISHED:資料檔案的另一部分被複制。

CALLBACK_STREAM_SWITCH:另一個流被創造并且将被複制。這是給出了第一次調用回調例程時的回調原因。

hSourceFile:源檔案的句柄。

hDestinationFile:目标檔案的句柄。

lpData:CopyFileEx等函數傳遞的參數

七。移動檔案/檔案更改名稱

1。MoveFile MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365239(v=vs.85).aspx 函數原型:

BOOL WINAPI MoveFile(
  _In_ LPCTSTR lpExistingFileName,
  _In_ LPCTSTR lpNewFileName
);
           

lpExistingFileName:原檔案名

lpNewFileName:目的檔案名 傳回值:成功傳回非0,失敗傳回0 注意:不支援跨卷移動檔案,可以使用CopyFile,然後DeleteFile,或者使用SHFileOperation

2.MoveFileWithProgress MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365242(v=vs.85).aspx 函數原型:

BOOL WINAPI MoveFileWithProgress(
  _In_     LPCTSTR            lpExistingFileName,
  _In_opt_ LPCTSTR            lpNewFileName,
  _In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine,
  _In_opt_ LPVOID             lpData,
  _In_     DWORD              dwFlags
);
           

lpExistingFileName:原檔案名

lpNewFileName:目的檔案名

lpProgressRoutine:指向一個回調函數的指針,回調函數用于接收移動進度等資訊

lpData:要傳給回調函數的資料指針

dwFlags:标志:(紅色為常用的)

MOVEFILE_COPY_ALLOWED:如果檔案移動到不同的卷,函數通過使用 CopyFile 和 DeleteFile 函數來模拟這一舉動。如果該檔案成功複制到一個不同的卷和原始檔案是不能被删除,此函數成功留下的源檔案的完整。使用此值不能同時用MOVEFILE_DELAY_UNTIL_REBOOT。

MOVEFILE_CREATE_HARDLINK:保留供将來使用。

MOVEFILE_DELAY_UNTIL_REBOOT:系統并不移動檔案,直到重新啟動作業系統。立即執行 AUTOCHK 後,但在建立任何分頁檔案之前,系統将該檔案移動。是以,此參數啟用的功能從先前啟動删除分頁檔案。如果過程是在使用者屬于管理者組或本地系統帳戶的上下文中,僅可以使用此值。此值不能用 MOVEFILE_COPY_ALLOWED。

MOVEFILE_FAIL_IF_NOT_TRACKABLE:如果源檔案是連結的源,但該檔案不能在移動後跟蹤函數将失敗。如果目标是用 FAT 檔案系統格式化的卷,可以出現這種情況。

MOVEFILE_REPLACE_EXISTING:如果檔案命名 lpNewFileName 存在,函數将其内容覆寫為lpExistingFileName 檔案的内容。如果 lpNewFileName 或 lpExistingFileName 是目錄,不能使用此值。

MOVEFILE_WRITE_THROUGH:函數不傳回直到檔案實際上已經在磁盤上。設定此值保證移動執行如拷貝和删除的操作重新整理到磁盤之前,該函數傳回。如果設定MOVEFILE_DELAY_UNTIL_REBOOT 此值沒有任何作用。

傳回值:成功傳回非0,失敗傳回0 回調函數:和上面的CopyProgressRoutine一樣 

繼續閱讀