在我关闭程序之前,C ++文件夹不会删除

时间:2014-04-11 20:48:39

标签: c++ windows

在我制作的游戏中,里面有文本文件的文件夹代表世界保存,在这个游戏的加载菜单中我想要一个删除保存的选项。我目前使用此代码尝试删除保存:

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());

2 个答案:

答案 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
  1. Windows路径使用\而不是/作为分隔符。许多API都会接受,但最终你会遇到一个没有的API,因此最好始终使用正确的API。

  2. FindFirstFile在失败时返回INVALID_HANDLE_VALUE(非NULL)。由于INVALID_HANDLE_VALUE不为零,因此您无法简单地测试if (hFile) { ... }

  3. API枚举文件和目录。旧代码试图错误地过滤掉...目录,这可能导致它跳过某些文件并尝试在其他目录上使用DeleteFile。跳过所有目录更简单(也更容易理解)。

  4. 不要在FindFirstFile返回的句柄上调用CloseHandle。

  5. 在FindFirstFile返回的句柄上调用FindClose,但只有在你从FindFirstFile获得有效句柄的情况下才这样做。

  6. 只要您使用特定于Windows的API,您也可以一致地使用它们,而不是与rmdir等库包装器混合使用。库包装器有时会引入令人惊讶的限制或行为,但我认为rmdir在这种情况下可以正常工作。

  7. 这仍然存在一个重大问题:它不会在路径中处理Unicode(并且它要求您编译ANSI以限制项目其他部分的Unicode处理。)