在我制作的游戏中,里面有文本文件的文件夹代表世界保存,在这个游戏的加载菜单中我想要一个删除保存的选项。我目前使用此代码尝试删除保存:
hFind = FindFirstFile((dir+"/*").c_str(), &FindFileData);
if (hFind){
do{
string s = FindFileData.cFileName;
if(s.find('.')){//prevents prossesing of "." and ".."
DeleteFile((dir+"/"+s).c_str());
}
}while(FindNextFile(hFind,&FindFileData));
CloseHandle(hFind);
}
rmdir(dir.c_str());
这些文件夹中唯一的东西是3个文本文件,所以这段代码应该足够了,但它不是。会发生什么事情是目录中的所有文件都被删除但文件夹没有,如果我尝试手动删除这个文件夹,或者在程序运行时以任何方式编辑它,Windows会拒绝我访问。但是一旦我关闭游戏,文件夹就会被删除。
我知道里面的文件被删除了,因为我尝试了上面的代码而没有" rmdir(dir.c_str());"并打开文件夹,所有文件都消失了,如果我"删除"保存,然后尝试加载它我没有世界,没有库存,表明文件已被删除。
我已经尝试使用removeDirectory并且同样的事情发生了,它还说它已成功删除而没有任何错误。
为什么会这样?我怎样才能避免这种情况,让它正常工作?
非常感谢任何帮助。
使用以下代码修复了该问题:
hFind = FindFirstFile((dir+"/*").c_str(), &FindFileData);
if (hFind){
do{
string s = FindFileData.cFileName;
if(s.find('.')){//prevents prossesing of "." and ".."
DeleteFile((dir+"/"+s).c_str());
}
}while(FindNextFile(hFind,&FindFileData));
CloseHandle(hFind);
}
findClose(hFind);
rmdir(dir.c_str());
答案 0 :(得分:4)
根据RemoveDirectory文档:
RemoveDirectory函数在关闭时标记要删除的目录。因此,在关闭目录的最后一个句柄之前,不会删除该目录。
可能你的程序将目录作为当前的工作目录,或者可能还有一个句柄打开它。
在windows中,rmdir是一个可比性函数,它调用本机窗口函数,因此它的行为相同。
答案 1 :(得分:0)
根本问题是CloseHandle
返回的句柄上的代码名为FindClose
而不是FindFirstFile
。
但代码还有几个错误。为了帮助未来的访客,这是更正后的代码。
HANDLE hFind = FindFirstFile((dir + "\\*").c_str(), &FindFileData); // See 1 below
if (hFind != INVALID_HANDLE_VALUE) { // 2
do {
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { // 3
const std::string s = dir + "\\" + FindFileData.cFileName;
DeleteFile(s.c_str());
}
} while (FindNextFile(hFind, &FindFileData));
// 4
FindClose(hFind); // 5
}
RemoveDirectory(dir.c_str()); // 6
Windows路径使用\
而不是/
作为分隔符。许多API都会接受,但最终你会遇到一个没有的API,因此最好始终使用正确的API。
FindFirstFile在失败时返回INVALID_HANDLE_VALUE(非NULL)。由于INVALID_HANDLE_VALUE不为零,因此您无法简单地测试if (hFile) { ... }
。
API枚举文件和目录。旧代码试图错误地过滤掉.
和..
目录,这可能导致它跳过某些文件并尝试在其他目录上使用DeleteFile。跳过所有目录更简单(也更容易理解)。
不要在FindFirstFile返回的句柄上调用CloseHandle。
在FindFirstFile返回的句柄上调用FindClose,但只有在你从FindFirstFile获得有效句柄的情况下才这样做。
只要您使用特定于Windows的API,您也可以一致地使用它们,而不是与rmdir等库包装器混合使用。库包装器有时会引入令人惊讶的限制或行为,但我认为rmdir在这种情况下可以正常工作。
这仍然存在一个重大问题:它不会在路径中处理Unicode(并且它要求您编译ANSI以限制项目其他部分的Unicode处理。)