2014-04-11 60 views
2

在我正在做的一個遊戲中,裏面的文本文件夾代表世界保存,在這個遊戲的加載菜單中,我想有一個選項來刪除保存。我目前使用此代碼嘗試刪除節省:C++文件夾不會刪除,直到我關閉程序

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和同樣的事情發生,它也說它已成功刪除沒有任何錯誤。

爲什麼會發生這種情況?我怎樣才能避免這種情況,並讓它正常工作?

任何幫助將不勝感激。


的問題fixxed用下面的代碼:

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

你應該堅持使用API​​並使用RemoveDirectory。 http://msdn.microsoft.com/en-us/library/aa365488%28VS.85%29.aspx如果刪除失敗,您檢查錯誤返回代碼並調用GetLastError()。 rmdir()不會給你這些信息(或者至少,很容易)。 – PaulMcKenzie

+0

您還應該檢查'DeleteFile'是否成功。 –

+0

隨着RemoveDirectory同樣的事情發生,並沒有發生錯誤,除非我單擊刪除不止一次,因爲該程序必須認爲該目錄已被刪除 – MurderFish612

回答

3

按照RemoveDirectory文檔:

RemoveDirectory功能,標誌着在近刪除的目錄。因此,目錄不會被刪除,直到目錄的最後一個句柄被關閉。

也許你的程序有目錄作爲它的當前工作目錄,或者也許還有一個處理它打開。

在windows中,rmdir是一個調用本機窗口函數的可比較函數,因此它的行爲相同。

+0

以及我關閉了我打開它的唯一句柄,除非有更多的我不知道這不應該是問題。我如何知道它是否是我當前的工作目錄,以及如何更改它? – MurderFish612

+0

您可以嘗試GetCurrentDirectory/SetCurrentDirectory http://msdn.microsoft.com/en-us/library/windows/desktop/aa365530(v=vs.85).aspx – harmic

+0

您還可以使用ProcessExplorer查看哪些句柄打開http ://stackoverflow.com/a/15722/1411457 – harmic

0

根本問題是代碼CloseHandle而不是FindCloseFindFirstFile返回的句柄。

但該代碼還有幾個錯誤。爲了幫助未來的訪問者,這是更正後的代碼。

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。

  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可以正常工作。

這仍然留下了顯著的問題:它不會在路徑處理Unicode(和它需要你編譯ANSI這就限制了統一處理項目的其他部分)。

相關問題