天天看點

MFC對目錄的遞歸建立、删除、拷貝和移動

直接貼代碼,我在本地測試過了。注意删除檔案時如果有隻讀檔案,也會遇到權限問題而導緻删除失敗,還有就是遞歸删除目錄在360等防毒軟體下會彈窗提示安全問題,畢竟是在大批量删除檔案,尤其是檔案夾帶有遊戲字樣時。

關于反斜杠和順斜杠,在windows裡,順斜杠隻是為了相容,但我在windows7裡使用順斜杠移動目錄,當目标目錄已經存在時,發現作業系統彈窗提示目标目錄不存在,是否建立,我點是或點否,都無法成功移動目錄。是以建議嚴格用反斜杠好了,在字元串裡,反斜杠要用轉義符,轉義符也是反斜杠,是以出現總是兩個反斜杠的寫法。

下面所有函數都來自網上搜尋,自己重構、測試後釋出的,如果覺得侵犯版權,請留言,我先貼出一些參考過的位址:

MFC 遞歸删除檔案夾下所有檔案或檔案夾

遞歸建立多級目錄

MFC拷貝檔案夾

MFC移動檔案夾

/**
 * 建立目錄(支援同時建立多級目錄)
 * 傳入參數:
 *     1 反斜杠:如D:\\1\\2\\或D:\\1\\2
 *     2 順斜杠:如D:/1/2/或D:/1/2
 * 參數最後的那個反斜杠可以有,也可以沒有。
 * 傳回值:成功或目錄本來已經存在時傳回TRUE,否則傳回FALSE
 * 注意:如果權限不足或目錄所在路徑本來是一個檔案,就會失敗。
 */
BOOL CreateFolder(const CString &folderPath)
{
	if (PathIsDirectory(folderPath))
	{
		return TRUE;
	}

	CString path = folderPath;

	TCHAR dirName[256] = {0};
	TCHAR *pFolderPath = path.GetBuffer(0);
	TCHAR *pDirName = dirName;
	while (*pFolderPath)
	{
		if (('\\' == *pFolderPath) || ('/' == *pFolderPath))
		{
			if (':' != *(pFolderPath - 1))
			{
				if (!PathIsDirectory(dirName) && !CreateDirectory(dirName, NULL))
				{
					return FALSE;
				}
			}
			if ('\0' == *(pFolderPath + 1))
			{
				return TRUE;
			}
		}

		*pDirName++ = *pFolderPath++;
		*pDirName = '\0';
	}

	return CreateDirectory(folderPath, NULL);
}
/**
 * 删除目錄(包括目錄中的所有目錄和檔案)
 * 傳入參數:
 *     1 反斜杠:如D:\\1\\2\\或D:\\1\\2
 *     2 順斜杠:如D:/1/2/或D:/1/2
 * 參數最後的那個反斜杠可以有,也可以沒有。
 * 傳回值:成功或目錄本來就不存在時傳回TRUE,否則傳回FALSE
 * 注意:如果權限不足或目錄所在路徑本來是一個檔案,就會失敗。
 */
BOOL DeleteFolder(const CString &folderPath)
{
	if (!PathIsDirectory(folderPath))
	{
		TRACE("OK\n");
		return TRUE;
	}
	CFileFind filefind;
	CString path = folderPath;
	if (path.Right(1) != "\\" && path.Right(1) != "/")
		path += "\\";
	path += "*.*";
	BOOL res = filefind.FindFile(path);
	while (res)
	{
		res = filefind.FindNextFile();
		if (!filefind.IsDots() && !filefind.IsDirectory())
		{
			CString filePath = filefind.GetFilePath();
			if (!DeleteFile(filePath))
			{
				return FALSE;
			}
		}
		else if (filefind.IsDots())
		{
			continue;
		}
		else if (filefind.IsDirectory())
		{
			CString pathDir = filefind.GetFilePath();
			if (!DeleteFolder(pathDir))
			{
				return FALSE;
			}
		}
	}
	return RemoveDirectory((LPCTSTR)folderPath);
}
/**
 * 遞歸拷貝目錄
 * 傳入參數:
 *     1 反斜杠:如D:\\1\\2\\或D:\\1\\2
 *     2 順斜杠:如D:/1/2/或D:/1/2
 * 參數最後的那個反斜杠可以有,也可以沒有。
 * 傳回值:成功傳回TRUE,否則傳回FALSE,如果目錄本來就存在可能會失敗!
 */
BOOL CopyFolder(CString strSrcPath, CString strTargetPath)
{
	if (!::PathFileExists(strTargetPath))
	{
		if (!CreateFolder(strTargetPath))
		{
			return FALSE;
		}
	}

	CFileFind finder;

	BOOL bWorking = finder.FindFile(strSrcPath);
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
		if (finder.IsDots())
		{
			continue;
		}
		else if (finder.IsDirectory())
		{
			if (!CopyFolder(finder.GetFilePath() + _T("\\*.*"), strTargetPath + _T("\\") + finder.GetFileName()))
			{
				return FALSE;
			}
		}
		else
		{
			if (!CopyFile(finder.GetFilePath(), strTargetPath + _T("\\") + finder.GetFileName(), FALSE))
			{
				return FALSE;
			}
		}
	}
	return TRUE;
}
/**
 * 遞歸移動目錄,注意并不是拷貝後删除,那樣效率太低了!
 * 傳入參數:
 *     1 隻允許反斜杠:如D:\\1\\2\\或D:\\1\\2
 * 參數最後的那個反斜杠可以有,也可以沒有。
 * 傳回值:成功傳回TRUE,否則傳回FALSE
 * 注意:順斜杠可能有一些問題。
 *       如果目标目錄本來就存在,第一次會導緻移動到該目錄下,第二次覆寫,比如D:/test到 D:/1/test,當D:/1/test目錄已經存在時
 */
BOOL MoveFolder(const char *strSrcPath, const char *strTargetPath)
{
	int srcLen = strlen(strSrcPath);
	int targetLen = strlen(strTargetPath);
	if (srcLen > 510 || targetLen > 510)
	{
		return FALSE;
	}
	char srcPath[512];
	char targetPath[512];
	strcpy(srcPath, strSrcPath);
	strcpy(targetPath, strTargetPath);
	srcPath[srcLen + 1] = 0;	   // 後2個位元組都必須為0
	targetPath[targetLen + 1] = 0; // 後2個位元組都必須為0

	SHFILEOPSTRUCT FileOp;
	ZeroMemory((void *)&FileOp, sizeof(SHFILEOPSTRUCT));
	FileOp.fFlags = FOF_NOCONFIRMATION;
	FileOp.hNameMappings = NULL;
	FileOp.hwnd = NULL;
	FileOp.lpszProgressTitle = NULL;
	FileOp.pFrom = strSrcPath;	// 源位址
	FileOp.pTo = strTargetPath; // 目的位址
	FileOp.wFunc = FO_MOVE;
	return 0 == SHFileOperation(&FileOp);
}
           

繼續閱讀