#pragma once
#include <string>
#include <vector>
#include <algorithm>
// SHFileOperation
#include <Shlwapi.h>
#pragma comment (lib,"Shlwapi.lib")
// iFileType,0:文件夹,1:文件
//void PrintFold(int iCurrentLevel, int iFileType, std::string strPath, std::string strFileName)
//{
// if (iFileType == 0)
// {
// printf(_T("文件夹:%d: %s\\%s\n"), iCurrentLevel, strPath.c_str(), strFileName.c_str());
// }
// else
// {
// printf(_T("文件:%d: %s\\%s\n"), iCurrentLevel, strPath.c_str(), strFileName.c_str());
// }
//}
// strPath的格式为c:/ss/ww
// iCurrentLevel:当前文件层级,0开始
// uiEndLevel:遍历层级深度,-1为遍历所有层级, 比如为0时只遍历当前目录
template<class TTraverseProcess>
bool TraverseFold(std::wstring strPath, TTraverseProcess& TP, std::wstring strWildcard = _T("\\*.*"), unsigned int uiEndLevel = -1, unsigned int iCurrentLevel = 0)
{
if (iCurrentLevel > uiEndLevel)
{// 到达遍历指定深度
return true;
}
WIN32_FIND_DATA findFileData;
std::wstring strFindPath = strPath + strWildcard; //这里一定要指明通配符,不然不会读取所有文件和目录
HANDLE hFind = ::FindFirstFile(strFindPath.c_str(), &findFileData);
if (INVALID_HANDLE_VALUE == hFind) {
return false;
}
//遍历文件夹
do
{
std::wstring strFileName = findFileData.cFileName;
if (strFileName != L"." && strFileName != L"..")
{//不是当前路径或者父目录的快捷方式
//printf(_T("%d: %s\\%s\n"), iCurrentLevel, strPath.c_str(), strFileName.c_str());
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{//是一个普通目录
//设置下一个将要扫描的文件夹路径
strFindPath = strPath + std::wstring(L"\\") + strFileName;
//遍历该目录
TraverseFold(strFindPath, TP, strWildcard, uiEndLevel, iCurrentLevel + 1);
// 处理函数对象
TP(iCurrentLevel, 0, strPath, strFileName);
}
else
{//是一个文件
TP(iCurrentLevel, 1, strPath, strFileName);
}
}
} while (::FindNextFile(hFind, &findFileData));//寻找下一个目录或者文件
::FindClose(hFind);
return true;
}
// 删除文件夹
bool KDeleteDirectory(std::wstring strDelDir, std::wstring& strErr)
{
class FindAllFiles
{
public:
void operator()(int iCurrentLevel, int iFileType, std::wstring strPath, std::wstring strFileName)
{
if (iFileType == 0)
{
//wprintf_s(L"文件夹:%d: %s\\%s\n", iCurrentLevel, strPath.c_str(), strFileName.c_str());
strFoldPathVec.push_back(std::pair<int, std::wstring>(iCurrentLevel, strPath + L"\\" + strFileName));
}
else
{
//wprintf_s(L"文件:%d: %s\\%s\n", iCurrentLevel, strPath.c_str(), strFileName.c_str());
strFilePathVec.push_back(strPath + L"\\" + strFileName);
}
}
public:
std::vector<std::wstring> strFilePathVec;
std::vector<std::pair<int, std::wstring>> strFoldPathVec;
};
//遍历所有考试文件夹,获取考试文件夹
FindAllFiles allFiles;
TraverseFold(strDelDir, allFiles, L"\\*.*");
for (size_t i = 0; i < allFiles.strFilePathVec.size(); ++i)
{
if (!::DeleteFile(allFiles.strFilePathVec[i].c_str()))
{
strErr = std::wstring(L"删除文件失败,") + allFiles.strFilePathVec[i];
return false;
}
}
std::sort(allFiles.strFoldPathVec.begin(), allFiles.strFoldPathVec.end(), [](std::pair<int, std::wstring>& lt, std::pair<int, std::wstring>& rt) {
return lt.first > rt.first;
});
for (size_t i = 0; i < allFiles.strFoldPathVec.size(); ++i)
{
if (!::RemoveDirectory(allFiles.strFoldPathVec[i].second.c_str()))
{
strErr = std::wstring(L"删除文件夹失败,") + allFiles.strFoldPathVec[i].second;
return false;
}
}
if (!::RemoveDirectory(strDelDir.c_str()))
{
strErr = std::wstring(L"删除文件夹失败,") + strDelDir;
return false;
}
return true;
}
bool KDeleteDirectorySH(std::wstring strDelDir, std::wstring& strErr)
{
SHFILEOPSTRUCTW FileOp;
FileOp.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;// | FOF_ALLOWUNDO/*删除到回收站*/
FileOp.hNameMappings = NULL;
FileOp.hwnd = NULL;
FileOp.lpszProgressTitle = NULL;
strDelDir.push_back('\0');
FileOp.pFrom = strDelDir.c_str();
FileOp.pTo = NULL;
FileOp.wFunc = FO_DELETE;
int iReturn = SHFileOperationW(&FileOp);
if (0 != iReturn)
{
strErr = std::wstring(L"删除文件夹失败,") + strDelDir;
return false;
}
return true;
}
既然有SHFileOperation,为什么要自己遍历文件夹呢,因为在实际使用中发现SHFileOperation非常耗时,自己遍历文件夹删除完大概只要几十毫秒,SHFileOperation则需要1秒多,很无语的,在删除大量文件夹时就会觉得进度很慢