MFC - 删除指定文件夹

C++删除文件夹及子文件夹
本文介绍了一个使用C++实现的递归删除指定文件夹及其所有子文件夹和文件的方法。通过调用Windows API函数RemoveDirectory和DeleteFile,并结合CFileFind类查找指定目录下的所有文件和子目录,确保了文件夹被完全清除。
// 删除指定的文件夹
 2 void DeleteDirectory(CString strDir)
 3 {
 4     if (strDir.IsEmpty())
 5     {
 6         RemoveDirectory(strDir);
 7         return;
 8     }
 9 
10     //首先删除文件及子文件夹 
11     CFileFind   ff;
12     BOOL bFound = ff.FindFile(strDir + _T("\\*"), 0);
13     while (bFound)
14     {
15         bFound = ff.FindNextFile();
16         if (ff.GetFileName() == _T(".") || ff.GetFileName() == _T(".."))        continue;
17 
18         //去掉文件(夹)只读等属性 
19         SetFileAttributes(ff.GetFilePath(), FILE_ATTRIBUTE_NORMAL);
20         if (ff.IsDirectory())
21         {
22             //递归删除子文件夹 
23             DeleteDirectory(ff.GetFilePath());
24             RemoveDirectory(ff.GetFilePath());
25         }
26         else
27         {
28             DeleteFile(ff.GetFilePath());   //删除文件 
29         }
30 
31     }
32 
33     ff.Close();
34 
35     //然后删除该文件夹 
36     RemoveDirectory(strDir);
37 }
<think> 我们在MFC(Microsoft Foundation Classes)环境下,判断Windows下指定文件夹是否存在。 通常有两种方法: 1. 使用Win32 API:如PathIsDirectory、GetFileAttributes等。 2. 使用C++标准库或MFC自带类(如CFileFind)。 这里我们采用两种常见方法: 方法一:使用GetFileAttributes函数(Win32 API) - 调用GetFileAttributes获取文件属性,然后检查返回的属性值是否包含FILE_ATTRIBUTE_DIRECTORY,并且返回值不等于INVALID_FILE_ATTRIBUTES。 方法二:使用CFileFind类(MFC- 使用CFileFind查找该目录,如果找到并且是目录,则存在。 下面分别给出两种方法的代码示例: 方法一:使用GetFileAttributes ```cpp #include <Windows.h> #include <tchar.h> bool FolderExists(LPCTSTR lpszFolderPath) { DWORD dwAttrib = GetFileAttributes(lpszFolderPath); return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } ``` 方法二:使用CFileFind ```cpp #include <afx.h> bool FolderExists(const CString& strFolderPath) { CFileFind finder; CString strPath = strFolderPath; // 确保路径以反斜杠结尾,这样我们查找的是目录 if (strPath.Right(1) != _T("\\")) strPath += _T("\\"); strPath += _T("*.*"); // 查找任意文件 BOOL bWorking = finder.FindFile(strPath); if (bWorking) { // 这里我们只需要知道是否存在,所以找到一个即可,但需要确认是目录 bWorking = finder.FindNextFile(); // 实际上,我们并不需要遍历,只要FindFile成功就说明该路径存在,但我们还要确认它是一个目录 // 然而,FindFile找到的第一个可能是文件,所以我们需要检查属性 // 注意:上述方法其实并不准确,因为即使目录为空,FindFile也会找到.和..,但非空目录会找到文件。 // 因此,更可靠的方法是直接检查目录属性。 // 所以,这里我们换一种方式:获取找到的第一个文件的属性,看是否是目录 // 但是注意:CFileFind::FindFile只是开始查找,我们需要调用FindNextFile直到找到一个目录或者文件? // 实际上,我们可以直接使用IsDirectory方法,但前提是我们已经找到了一个文件(或目录)。 // 由于我们添加了*.*,所以即使目录为空,也会返回两个虚拟目录:.和..,这两个都是目录。 // 因此,我们可以直接判断: if (finder.IsDirectory()) { finder.Close(); return true; } // 否则,我们继续找下一个? // 但是注意,我们可能在一个有很多文件的目录中,我们不关心文件,所以我们要尝试找到目录项。 // 实际上,我们可以简化:只要FindFile成功,并且路径是一个目录(我们可以通过路径本身判断,但这里我们已经用CFileFind了,它提供了IsDirectory) // 但是上面的代码在找到第一个文件时,如果第一个文件不是目录,那么就会返回false,但实际上目录存在,只是里面包含文件。 // 因此,这种方法不可靠。 // 更正:其实我们并不需要遍历里面的文件,我们只需要判断指定的路径是否是目录。所以方法一更直接。 // 因此,使用CFileFind的正确方法是,我们并不需要查找里面的文件,而是直接查找这个目录本身: // 我们将路径设置为要查找的目录(不带通配符) // 但是,CFileFind只能用于查找文件(包括目录)的通配符匹配。所以我们可以这样: // 直接查找这个目录(不带后面的*.*),然后判断是否找到且是目录。 // 所以,我们重新写一个版本: } finder.Close(); return false; } ``` 实际上,使用CFileFind来判断单个目录是否存在,可以这样: ```cpp bool FolderExists(const CString& strFolderPath) { CFileFind finder; BOOL bFound = finder.FindFile(strFolderPath); if (bFound) { bFound = finder.FindNextFile(); // 实际上,FindFile只是开始,FindNextFile才是获取第一个结果 // 但是我们这里只有一个结果(目录本身),所以调用一次FindNextFile就可以得到 // 不过,如果目录存在,FindFile会返回TRUE,然后我们调用FindNextFile得到第一个匹配项(也就是目录本身) // 但是注意:如果路径是一个目录,那么FindFile会把它当作一个匹配项(通配符匹配),但是我们的路径没有通配符,所以就是它本身。 if (finder.IsDirectory()) { finder.Close(); return true; } } finder.Close(); return false; } ``` 但是,这种方法并不常用,而且对于根目录(如C:\)可能有问题。 因此,推荐使用方法一(GetFileAttributes)来判断文件夹是否存在。 下面给出完整的MFC示例代码(使用方法一): 假设我们要判断的文件夹路径是C:\TestFolder 在MFC的按钮点击事件或其他函数中: ```cpp void CMyDialog::OnButtonCheckFolder() { CString strFolderPath = _T("C:\\TestFolder"); if (FolderExists(strFolderPath)) { AfxMessageBox(_T("文件夹存在!")); } else { AfxMessageBox(_T("文件夹不存在!")); } } ``` 其中,FolderExists函数我们写成: ```cpp bool CMyDialog::FolderExists(LPCTSTR lpszFolderPath) { DWORD dwAttrib = GetFileAttributes(lpszFolderPath); return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } ``` 注意:如果路径中包含末尾的反斜杠,例如"C:\\TestFolder\\",GetFileAttributes也能正常工作。 解释: GetFileAttributes函数返回文件或目录的属性。如果函数失败,返回INVALID_FILE_ATTRIBUTES。如果成功,则检查返回的属性值是否包含FILE_ATTRIBUTE_DIRECTORY(表示这是一个目录)。 因此,以上代码是判断文件夹存在的可靠方法。 相关问题: §§相关问题§§: 1. 如何使用MFC创建多级目录(类似Linux下的mkdir -p)? 2. 在Windows API中,如何递归删除一个目录及其所有子目录和文件? 3. 使用MFC的CFileFind类遍历一个目录下的所有文件(包括子目录)的示例代码? 4. 如何判断一个路径是文件还是目录? </think> 在 MFC 中判断指定文件夹是否存在,可以使用 Windows API 的 `GetFileAttributes` 函数。以下是详细实现和解释: ### 解决方案代码 ```cpp #include <Windows.h> bool FolderExists(LPCTSTR lpszFolderPath) { // 获取文件/目录属性 DWORD dwAttrib = GetFileAttributes(lpszFolderPath); // 检查属性是否有效且是目录 return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } // 使用示例 void CheckFolder() { LPCTSTR folderPath = _T("C:\\MyFolder"); if (FolderExists(folderPath)) { AfxMessageBox(_T("文件夹存在")); } else { AfxMessageBox(_T("文件夹不存在")); } } ``` ### 代码解释 1. **`GetFileAttributes` 函数**: - Windows API 函数,返回文件或目录的属性 - 参数 `LPCTSTR`: 目录路径(支持 Unicode/ANSI) - 返回值: - `INVALID_FILE_ATTRIBUTES` (0xFFFFFFFF): 路径无效 - 其他值: 属性位掩码 2. **关键检查逻辑**: - `dwAttrib != INVALID_FILE_ATTRIBUTES`: 排除无效路径 - `dwAttrib & FILE_ATTRIBUTE_DIRECTORY`: 检查返回属性是否包含目录标志位 3. **注意事项**: - 路径格式:使用双反斜杠 `\\` 或正斜杠 `/` - 权限要求:调用进程需对路径有读取权限 - 特殊路径:支持网络路径 (`\\server\share`) 和相对路径 - 末尾斜杠:路径末尾的 `\` 不影响判断结果 4. **MFC 适配**: - 可直接在对话框/文档类中使用 - 支持 `CString` 路径:`FolderExists(strPath.GetString())` - 兼容 Unicode 项目(使用 `_T` 宏) ### 替代方案对比 | 方法 | 优点 | 缺点 | |---------------------|-----------------------|--------------------------| | `GetFileAttributes` | 最简洁高效,官方推荐 | 需手动检查属性标志位 | | `PathIsDirectory` | 语义更明确 | 需额外链接 `Shlwapi.lib` | | `FindFirstFile` | 可获取详细信息 | 代码较复杂,开销较大 | 如果需要使用 `PathIsDirectory` 方案: ```cpp #include <Shlwapi.h> #pragma comment(lib, "Shlwapi.lib") bool FolderExists(LPCTSTR path) { return PathIsDirectory(path) && PathFileExists(path); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BeanGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值