原文鏈接:http://www.cnblogs.com/xianyunhe/archive/2011/12/06/2278550.html
文件和文件夾的創建、復制、刪除、重命名等操作是經常要用到的,作者根據自己的經驗,並查詢了MSDN,特意總結了常用文件和文件夾的相關操作,重點討論了復制整個文件夾和刪除整個文件夾
1、文件操作基本函數
WinBase.h中聲明了Windows平台下的基本的API函數,包括文件和目錄的基本操作。
下面列出部分常用的文件操作相關函數。
函數 |
說明 |
DeleteFile |
刪除單個文件,不能刪除目錄和只讀文件 |
CopyFile |
復制單個文件 |
MoveFile |
移動移動文件或目錄 |
CreateDirectory |
創建目錄 |
RemoveDirectory |
刪除空目錄 |
更多的函數可查詢Winbase.h文件或者MSDN中的File Management Functions和Directory Management Functions 。
2、復制目錄和刪除目錄
WinBase.h中的文件操作函數中並沒有直接實現整個文件夾的復制和刪除操作的函數,需要自己實現。
(1)判斷指定路徑是否有效目錄
1 /*判斷一個路徑是否是已存在的目錄*/
2 BOOL IsDirectory(LPCTSTR pstrPath)
3 {
4 if (NULL == pstrPath)
5 {
6 return FALSE;
7 }
8
9 /*去除路徑末尾的反斜杠*/
10 CString strPath = pstrPath;
11 if (strPath.Right(1) == _T('\\'))
12 {
13 strPath.Delete(strPath.GetLength()-1);
14 }
15
16 CFileFind finder;
17 BOOL bRet = finder.FindFile(strPath);
18 if (!bRet)
19 {
20 return FALSE;
21 }
22
23 /*判斷該路徑是否是目錄*/
24 finder.FindNextFile();
25 bRet = finder.IsDirectory();
26 finder.Close();
27 return bRet;
28 }
(2)復制目錄
復制目錄函數的大致思路為:查找目錄中所有文件,如果是文件直接復制,如果是目錄,則遞歸調用目錄復制函數。
1 /*復制目錄中的所有內容*/
2 BOOL CopyFolder(LPCTSTR pstrSrcFolder, LPCTSTR pstrDstFolder)
3 {
4 if ((NULL == pstrSrcFolder) || (NULL == pstrSrcFolder))
5 {
6 return FALSE;
7 }
8
9 /*檢查源目錄是否是合法目錄*/
10 if (!IsDirectory(pstrSrcFolder))
11 {
12 return FALSE;
13 }
14
15 /*把文件名稱轉換為CString類型,並確認目錄的路徑末尾為反斜杠*/
16 CString strSrcFolder(pstrSrcFolder);
17 if (strSrcFolder.Right(1) != _T('\\'))
18 {
19 strSrcFolder += _T("\\");
20 }
21 CString strDstFolder(pstrDstFolder);
22 if (strDstFolder.Right(1) != _T("\\"))
23 {
24 strDstFolder += _T("\\");
25 }
26
27 /*如果是目錄自身復制,直接返回復制成功*/
28 if (0 == _tcscmp(strSrcFolder, strDstFolder))
29 {
30 return TRUE;
31 }
32
33 /*如果目的目錄不存在,則創建目錄*/
34 if (!IsDirectory(strDstFolder))
35 {
36 if (!CreateDirectory(strDstFolder, NULL))
37 {
38 /*創建目的目錄失敗*/
39 return FALSE;
40 }
41 }
42
43 /*創建源目錄中查找文件的通配符*/
44 CString strWildcard(strSrcFolder);
45 strWildcard += _T("*.*");
46
47 /*打開文件查找,查看源目錄中是否存在匹配的文件*/
48 /*調用FindFile后,必須調用FindNextFile才能獲得查找文件的信息*/
49 CFileFind finder;
50 BOOL bWorking = finder.FindFile(strWildcard);
51
52 while (bWorking)
53 {
54 /*查找下一個文件*/
55 bWorking = finder.FindNextFile();
56
57 /*跳過當前目錄“.”和上一級目錄“..”*/
58 if (finder.IsDots())
59 {
60 continue;
61 }
62
63 /*得到當前要復制的源文件的路徑*/
64 CString strSrcFile = finder.GetFilePath();
65
66 /*得到要復制的目標文件的路徑*/
67 CString strDstFile(strDstFolder);
68 strDstFile += finder.GetFileName();
69
70 /*判斷當前文件是否是目錄,*/
71 /*如果是目錄,遞歸調用復制目錄,*/
72 /*否則,直接復制文件*/
73 if (finder.IsDirectory())
74 {
75 if (!CopyFolder(strSrcFile, strDstFile))
76 {
77 finder.Close();
78 return FALSE;
79 }
80 }
81 else
82 {
83 if (!CopyFile(strSrcFile, strDstFile, FALSE))
84 {
85 finder.Close();
86 return FALSE;
87 }
88 }
89
90 } /*while (bWorking)*/
91
92 /*關閉文件查找*/
93 finder.Close();
94
95 return TRUE;
96
97 }
(3)刪除目錄
刪除目錄的思路和復制目錄的思路類似,也是采用遞歸的方法。
1 /*刪除目錄及目錄中的所有內容*/
2 BOOL DeleteFolder(LPCTSTR pstrFolder)
3 {
4 if ((NULL == pstrFolder))
5 {
6 return FALSE;
7 }
8
9 /*檢查輸入目錄是否是合法目錄*/
10 if (!IsDirectory(pstrFolder))
11 {
12 return FALSE;
13 }
14
15 /*創建源目錄中查找文件的通配符*/
16 CString strWildcard(pstrFolder);
17 if (strWildcard.Right(1) != _T('\\'))
18 {
19 strWildcard += _T("\\");
20 }
21 strWildcard += _T("*.*");
22
23 /*打開文件查找,查看源目錄中是否存在匹配的文件*/
24 /*調用FindFile后,必須調用FindNextFile才能獲得查找文件的信息*/
25 CFileFind finder;
26 BOOL bWorking = finder.FindFile(strWildcard);
27
28 while (bWorking)
29 {
30 /*查找下一個文件*/
31 bWorking = finder.FindNextFile();
32
33 /*跳過當前目錄“.”和上一級目錄“..”*/
34 if (finder.IsDots())
35 {
36 continue;
37 }
38
39 /*得到當前目錄的子文件的路徑*/
40 CString strSubFile = finder.GetFilePath();
41
42 /*判斷當前文件是否是目錄,*/
43 /*如果是目錄,遞歸調用刪除目錄,*/
44 /*否則,直接刪除文件*/
45 if (finder.IsDirectory())
46 {
47 if (!DeleteFolder(strSubFile))
48 {
49 finder.Close();
50 return FALSE;
51 }
52 }
53 else
54 {
55 if (!DeleteFile(strSubFile))
56 {
57 finder.Close();
58 return FALSE;
59 }
60 }
61
62 } /*while (bWorking)*/
63
64 /*關閉文件查找*/
65 finder.Close();
66
67 /*刪除空目錄*/
68 return RemoveDirectory(pstrFolder);
69 }
3、shlwapi.h中的文件操作函數
shlwapi.h是shlwapi.dll頭文件,shlwapi.dll(Microsoft Shell Light-weight Utility Library)中定義了路徑相關的操作,也包括了部分文件操作函數。由於shlwapi.dll屬於Microsoft Windows Shell,因此這些文件操作特點與通過Shell進行文件操作類似。
下面列出部分常用的文件操作相關函數。
PathIsDirectory |
判斷一個路徑是否有效目錄 |
PathIsDirectoryEmpty |
判斷一個路徑是否空目錄 |
PathFileExists |
判斷一個路徑是否有效目錄或文件 |
PathRenameExtension |
更改文件的后綴名 |
SHFileOperation |
可實現文件或目錄的復制、移動、重命名和刪除操作,並可一次操作多個文件或目錄 |
其中,SHFileOperation可實現整個目錄的內容的復制和刪除。SHFileOperation可一次實現多個目錄的復制或刪除,其輸入參數結構體SHFILEOPSTRUCT中的pFrom(源目錄)和pTo(目的目錄)都可以輸入多個目錄,目錄之間通過'\0'分割,pFrom和pTo必須以2個'\0'結尾。一般情況下,我們都只是對一個目錄操作,因此,SHFileOperation調用並不是很方便,下面就對SHFileOperation進行包裝,提供更方便調用的目錄操作函數。
具體的代碼實現如下:
(1)復制目錄
1 /*通過調用ShFileOperation來實現整個目錄的復制*/
2 /*只復制單個目錄*/
3 /*如果目標目錄已存在,將把源目錄作為目的目錄的子目錄*/
4 /*如果要實現完全覆蓋,需要先刪除目的目錄*/
5 BOOL SHCopyFolder(LPCTSTR pstrSrcFolder, LPCTSTR pstrDstFolder)
6 {
7 if ((NULL == pstrSrcFolder) || (NULL == pstrSrcFolder))
8 {
9 return FALSE;
10 }
11
12 int iSrcPathLen = _tcslen(pstrSrcFolder);
13 int iDstPathLen = _tcslen(pstrDstFolder);
14 if ((iSrcPathLen >= MAX_PATH) || (iDstPathLen >= MAX_PATH))
15 {
16 return FALSE;
17 }
18
19 /*確保源目錄的路徑以2個\0結尾*/
20 TCHAR tczSrcFolder[MAX_PATH+1];
21 ZeroMemory(tczSrcFolder, (MAX_PATH+1)*sizeof(TCHAR));
22 _tcscpy(tczSrcFolder, pstrSrcFolder);
23 tczSrcFolder[iSrcPathLen] = _T('\0');
24 tczSrcFolder[iSrcPathLen+1] = _T('\0');
25
26 /*確保目的目錄的路徑以2個\0結尾*/
27 TCHAR tczDstFolder[MAX_PATH+1];
28 ZeroMemory(tczDstFolder, (MAX_PATH+1)*sizeof(TCHAR));
29 _tcscpy(tczDstFolder, pstrDstFolder);
30 tczDstFolder[iDstPathLen] = _T('\0');
31 tczDstFolder[iDstPathLen+1] = _T('\0');
32
33 SHFILEOPSTRUCT FileOp;
34 ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
35 FileOp.fFlags |= FOF_SILENT; /*不顯示進度*/
36 FileOp.fFlags |= FOF_NOERRORUI ; /*不報告錯誤信息*/
37 FileOp.fFlags |= FOF_NOCONFIRMATION;/*不進行確認*/
38 FileOp.hNameMappings = NULL;
39 FileOp.hwnd = NULL;
40 FileOp.lpszProgressTitle = NULL;
41 FileOp.wFunc = FO_COPY;
42 FileOp.pFrom = tczSrcFolder; /*源目錄,必須以2個\0結尾*/
43 FileOp.pTo = tczDstFolder; /*目的目錄,必須以2個\0結尾*/
44
45 /*復制目錄*/
46 if (0 == SHFileOperation(&FileOp))
47 {
48 return TRUE;
49 }
50 else
51 {
52 return FALSE;
53 }
54
55 }
(2)刪除目錄
1 /*通過調用ShFileOperation來實現整個目錄的刪除*/
2 /*只刪除單個目錄*/
3 BOOL CFolder::SHDeleteFolder(LPCTSTR pstrFolder, BOOL bAllowUndo)
4 {
5 if ((NULL == pstrFolder))
6 {
7 return FALSE;
8 }
9
10 int iPathLen = _tcslen(pstrFolder);
11 if (iPathLen >= MAX_PATH)
12 {
13 return FALSE;
14 }
15
16 /*確保目錄的路徑以2個\0結尾*/
17 TCHAR tczFolder[MAX_PATH+1];
18 ZeroMemory(tczFolder, (MAX_PATH+1)*sizeof(TCHAR));
19 _tcscpy(tczFolder, pstrFolder);
20 tczFolder[iPathLen] = _T('\0');
21 tczFolder[iPathLen+1] = _T('\0');
22
23 SHFILEOPSTRUCT FileOp;
24 ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
25 FileOp.fFlags |= FOF_SILENT; /*不顯示進度*/
26 FileOp.fFlags |= FOF_NOERRORUI; /*不報告錯誤信息*/
27 FileOp.fFlags |= FOF_NOCONFIRMATION;/*直接刪除,不進行確認*/
28 FileOp.hNameMappings = NULL;
29 FileOp.hwnd = NULL;
30 FileOp.lpszProgressTitle = NULL;
31 FileOp.wFunc = FO_DELETE;
32 FileOp.pFrom = tczFolder; /*要刪除的目錄,必須以2個\0結尾*/
33 FileOp.pTo = NULL;
34
35 /*根據傳遞的bAllowUndo參數確定是否刪除到回收站*/
36 if (bAllowUndo)
37 {
38 FileOp.fFlags |= FOF_ALLOWUNDO; /*刪除到回收站*/
39 }
40 else
41 {
42 FileOp.fFlags &= ~FOF_ALLOWUNDO; /*直接刪除,不放入回收站*/
43 }
44
45 /*刪除目錄*/
46 if (0 == SHFileOperation(&FileOp))
47 {
48 return TRUE;
49 }
50 else
51 {
52 return FALSE;
53 }
54 }
4、示例工程
作者通過VC6.0和VS2010分別針對以上代碼創建了示例工程,在工程中,把以上函數封裝到CFolder類中,並把所有函數設置為靜態函數。在示例工程中,分別對這些函數進行了調用測試。
工程文件下載:
PUDN:http://www.pudn.com/downloads404/sourcecode/windows/file/detail1723045.html
CSDN:http://download.csdn.net/detail/xianyunhe1234/3888994
5、參考資料
(1)、File Management Functions
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364232(v=vs.85).aspx
(2)、Directory Management Functions
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363950(v=vs.85).aspx