資料夾複製和刪除整個資料夾
轉載請註明原文連結。
檔案和資料夾的建立、複製、刪除、重新命名等操作是經常要用到的,作者根據自己的經驗,並查詢了MSDN,特意總結了常用檔案和資料夾的相關操作,重點討論了複製整個資料夾和刪除整個資料夾
1、檔案操作基本函式
WinBase.h中聲明瞭Windows平臺下的基本的API函式,包括檔案和目錄的基本操作。
下面列出部分常用的檔案操作相關函式。
函式 |
說明 |
DeleteFile |
刪除單個檔案,不能刪除目錄和只讀檔案 |
CopyFile |
複製單個檔案 |
MoveFile |
移動移動檔案或目錄 |
CreateDirectory |
建立目錄 |
RemoveDirectory |
刪除空目錄 |
更多的函式可查詢Winbase.h檔案或者MSDN中的File Management Functions和Directory Management Functions 。
2、複製目錄和刪除目錄
WinBase.h中的檔案操作函式中並沒有直接實現整個資料夾的複製和刪除操作的函式,需要自己實現。
(1)判斷指定路徑是否有效目錄
/*判斷一個路徑是否是已存在的目錄*/ BOOL IsDirectory(LPCTSTR pstrPath) { if (NULL == pstrPath) { return FALSE; } /*去除路徑末尾的反斜槓*/ CString strPath = pstrPath; if (strPath.Right(1) == _T('\\')) { strPath.Delete(strPath.GetLength()-1); } CFileFind finder; BOOL bRet = finder.FindFile(strPath); if (!bRet) { return FALSE; } /*判斷該路徑是否是目錄*/ finder.FindNextFile(); bRet = finder.IsDirectory(); finder.Close(); return bRet; }
(2)複製目錄
複製目錄函式的大致思路為:查詢目錄中所有檔案,如果是檔案直接複製,如果是目錄,則遞迴呼叫目錄複製函式。
/*複製目錄中的所有內容*/ BOOL CopyFolder(LPCTSTR pstrSrcFolder, LPCTSTR pstrDstFolder) { if ((NULL == pstrSrcFolder) || (NULL == pstrSrcFolder)) { return FALSE; } /*檢查源目錄是否是合法目錄*/ if (!IsDirectory(pstrSrcFolder)) { return FALSE; } /*把檔名稱轉換為CString型別,並確認目錄的路徑末尾為反斜槓*/ CString strSrcFolder(pstrSrcFolder); if (strSrcFolder.Right(1) != _T('\\')) { strSrcFolder += _T("\\"); } CString strDstFolder(pstrDstFolder); if (strDstFolder.Right(1) != _T("\\")) { strDstFolder += _T("\\"); } /*如果是目錄自身複製,直接返回複製成功*/ if (0 == _tcscmp(strSrcFolder, strDstFolder)) { return TRUE; } /*如果目的目錄不存在,則建立目錄*/ if (!IsDirectory(strDstFolder)) { if (!CreateDirectory(strDstFolder, NULL)) { /*建立目的目錄失敗*/ return FALSE; } } /*建立源目錄中查詢檔案的萬用字元*/ CString strWildcard(strSrcFolder); strWildcard += _T("*.*"); /*開啟檔案查詢,檢視源目錄中是否存在匹配的檔案*/ /*呼叫FindFile後,必須呼叫FindNextFile才能獲得查詢檔案的資訊*/ CFileFind finder; BOOL bWorking = finder.FindFile(strWildcard); while (bWorking) { /*查詢下一個檔案*/ bWorking = finder.FindNextFile(); /*跳過當前目錄“.”和上一級目錄“..”*/ if (finder.IsDots()) { continue; } /*得到當前要複製的原始檔的路徑*/ CString strSrcFile = finder.GetFilePath(); /*得到要複製的目標檔案的路徑*/ CString strDstFile(strDstFolder); strDstFile += finder.GetFileName(); /*判斷當前檔案是否是目錄,*/ /*如果是目錄,遞迴呼叫複製目錄,*/ /*否則,直接複製檔案*/ if (finder.IsDirectory()) { if (!CopyFolder(strSrcFile, strDstFile)) { finder.Close(); return FALSE; } } else { if (!CopyFile(strSrcFile, strDstFile, FALSE)) { finder.Close(); return FALSE; } } } /*while (bWorking)*/ /*關閉檔案查詢*/ finder.Close(); return TRUE; }
(3)刪除目錄
刪除目錄的思路和複製目錄的思路類似,也是採用遞迴的方法。
/*刪除目錄及目錄中的所有內容*/
BOOL DeleteFolder(LPCTSTR pstrFolder)
{
if ((NULL == pstrFolder))
{
return FALSE;
}
/*檢查輸入目錄是否是合法目錄*/
if (!IsDirectory(pstrFolder))
{
return FALSE;
}
/*建立源目錄中查詢檔案的萬用字元*/
CString strWildcard(pstrFolder);
if (strWildcard.Right(1) != _T('\\'))
{
strWildcard += _T("\\");
}
strWildcard += _T("*.*");
/*開啟檔案查詢,檢視源目錄中是否存在匹配的檔案*/
/*呼叫FindFile後,必須呼叫FindNextFile才能獲得查詢檔案的資訊*/
CFileFind finder;
BOOL bWorking = finder.FindFile(strWildcard);
while (bWorking)
{
/*查詢下一個檔案*/
bWorking = finder.FindNextFile();
/*跳過當前目錄“.”和上一級目錄“..”*/
if (finder.IsDots())
{
continue;
}
/*得到當前目錄的子檔案的路徑*/
CString strSubFile = finder.GetFilePath();
/*判斷當前檔案是否是目錄,*/
/*如果是目錄,遞迴呼叫刪除目錄,*/
/*否則,直接刪除檔案*/
if (finder.IsDirectory())
{
if (!DeleteFolder(strSubFile))
{
finder.Close();
return FALSE;
}
}
else
{
if (!DeleteFile(strSubFile))
{
finder.Close();
return FALSE;
}
}
} /*while (bWorking)*/
/*關閉檔案查詢*/
finder.Close();
/*刪除空目錄*/
return RemoveDirectory(pstrFolder);
}
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)複製目錄
/*通過呼叫ShFileOperation來實現整個目錄的複製*/
/*只複製單個目錄*/
/*如果目標目錄已存在,將把源目錄作為目的目錄的子目錄*/
/*如果要實現完全覆蓋,需要先刪除目的目錄*/
BOOL SHCopyFolder(LPCTSTR pstrSrcFolder, LPCTSTR pstrDstFolder)
{
if ((NULL == pstrSrcFolder) || (NULL == pstrSrcFolder))
{
return FALSE;
}
int iSrcPathLen = _tcslen(pstrSrcFolder);
int iDstPathLen = _tcslen(pstrDstFolder);
if ((iSrcPathLen >= MAX_PATH) || (iDstPathLen >= MAX_PATH))
{
return FALSE;
}
/*確保源目錄的路徑以2個\0結尾*/
TCHAR tczSrcFolder[MAX_PATH+1];
ZeroMemory(tczSrcFolder, (MAX_PATH+1)*sizeof(TCHAR));
_tcscpy(tczSrcFolder, pstrSrcFolder);
tczSrcFolder[iSrcPathLen] = _T('\0');
tczSrcFolder[iSrcPathLen+1] = _T('\0');
/*確保目的目錄的路徑以2個\0結尾*/
TCHAR tczDstFolder[MAX_PATH+1];
ZeroMemory(tczDstFolder, (MAX_PATH+1)*sizeof(TCHAR));
_tcscpy(tczDstFolder, pstrDstFolder);
tczDstFolder[iDstPathLen] = _T('\0');
tczDstFolder[iDstPathLen+1] = _T('\0');
SHFILEOPSTRUCT FileOp;
ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
FileOp.fFlags |= FOF_SILENT; /*不顯示進度*/
FileOp.fFlags |= FOF_NOERRORUI ; /*不報告錯誤資訊*/
FileOp.fFlags |= FOF_NOCONFIRMATION;/*不進行確認*/
FileOp.hNameMappings = NULL;
FileOp.hwnd = NULL;
FileOp.lpszProgressTitle = NULL;
FileOp.wFunc = FO_COPY;
FileOp.pFrom = tczSrcFolder; /*源目錄,必須以2個\0結尾*/
FileOp.pTo = tczDstFolder; /*目的目錄,必須以2個\0結尾*/
/*複製目錄*/
if (0 == SHFileOperation(&FileOp))
{
return TRUE;
}
else
{
return FALSE;
}
}
(2)刪除目錄
/*通過呼叫ShFileOperation來實現整個目錄的刪除*/
/*只刪除單個目錄*/
BOOL CFolder::SHDeleteFolder(LPCTSTR pstrFolder, BOOL bAllowUndo)
{
if ((NULL == pstrFolder))
{
return FALSE;
}
int iPathLen = _tcslen(pstrFolder);
if (iPathLen >= MAX_PATH)
{
return FALSE;
}
/*確保目錄的路徑以2個\0結尾*/
TCHAR tczFolder[MAX_PATH+1];
ZeroMemory(tczFolder, (MAX_PATH+1)*sizeof(TCHAR));
_tcscpy(tczFolder, pstrFolder);
tczFolder[iPathLen] = _T('\0');
tczFolder[iPathLen+1] = _T('\0');
SHFILEOPSTRUCT FileOp;
ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
FileOp.fFlags |= FOF_SILENT; /*不顯示進度*/
FileOp.fFlags |= FOF_NOERRORUI; /*不報告錯誤資訊*/
FileOp.fFlags |= FOF_NOCONFIRMATION;/*直接刪除,不進行確認*/
FileOp.hNameMappings = NULL;
FileOp.hwnd = NULL;
FileOp.lpszProgressTitle = NULL;
FileOp.wFunc = FO_DELETE;
FileOp.pFrom = tczFolder; /*要刪除的目錄,必須以2個\0結尾*/
FileOp.pTo = NULL;
/*根據傳遞的bAllowUndo引數確定是否刪除到回收站*/
if (bAllowUndo)
{
FileOp.fFlags |= FOF_ALLOWUNDO; /*刪除到回收站*/
}
else
{
FileOp.fFlags &= ~FOF_ALLOWUNDO; /*直接刪除,不放入回收站*/
}
/*刪除目錄*/
if (0 == SHFileOperation(&FileOp))
{
return TRUE;
}
else
{
return FALSE;
}
}
4、示例工程
作者通過VC6.0和VS2010分別針對以上程式碼建立了示例工程,在工程中,把以上函式封裝到CFolder類中,並把所有函式設定為靜態函式。在示例工程中,分別對這些函式進行了呼叫測試。
工程檔案下載:
5、參考資料
(1)、File Management Functions
(2)、Directory Management Functions