2009-04-09 141 views
26

如何使用C++刪除文件夾?如果不存在跨平臺的方式,那麼如何爲最流行的操作系統 - Windows,Linux,Mac,iOS,Android?做到這一點。 POSIX解決方案是否適用於所有這些解決方案?如何刪除C++中的文件夾?

回答

0

C++標準定義了remove()函數,它可能會或可能不會刪除文件夾,具體取決於實現。如果不是,則需要使用特定於實現的功能,例如rmdir()。

4

的目錄必須是空的,你的程序必須有權限刪除它

但函數調用命令rmdir會做

rmdir("C:/Documents and Settings/user/Desktop/itsme") 
+4

你在Windows中使用什麼頭文件? – 2011-09-26 22:23:17

+0

使用_rmdir for windows,並且標題爲 `#include `我相信,與_mkdir相同 – Mich 2018-01-17 01:49:43

8

的目錄應該是空的。

BOOL RemoveDirectory(LPCTSTR lpPathName); 
+12

這只是我認爲的Windows? Vinay擁有Apple頭像,但發佈了Windows特定的答案,我覺得很有趣。 ;) – Aardvark 2009-04-09 15:36:31

+9

Vinay已經沒有Apple頭像了) – sergtk 2012-08-31 02:20:00

+3

Vinay現在有一個Android頭像:) – 2015-09-16 09:41:03

-2

如果您使用的是windows,那麼看看this link。否則,你可能會尋找你的操作系統特定的版本api。我不認爲C++採用跨平臺的方式來實現它。最後,這不是C++的工作,而是操作系統的工作。

16

刪除文件夾在Windows(VISUALC++)不使用殼牌的API(sub_folders和文件),這是最好的工作樣本:

#include <string> 
#include <iostream> 

#include <windows.h> 
#include <conio.h> 


int DeleteDirectory(const std::string &refcstrRootDirectory, 
        bool    bDeleteSubdirectories = true) 
{ 
    bool   bSubdirectory = false;  // Flag, indicating whether 
               // subdirectories have been found 
    HANDLE   hFile;      // Handle to directory 
    std::string  strFilePath;     // Filepath 
    std::string  strPattern;     // Pattern 
    WIN32_FIND_DATA FileInformation;    // File information 


    strPattern = refcstrRootDirectory + "\\*.*"; 
    hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation); 
    if(hFile != INVALID_HANDLE_VALUE) 
    { 
    do 
    { 
     if(FileInformation.cFileName[0] != '.') 
     { 
     strFilePath.erase(); 
     strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName; 

     if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
     { 
      if(bDeleteSubdirectories) 
      { 
      // Delete subdirectory 
      int iRC = DeleteDirectory(strFilePath, bDeleteSubdirectories); 
      if(iRC) 
       return iRC; 
      } 
      else 
      bSubdirectory = true; 
     } 
     else 
     { 
      // Set file attributes 
      if(::SetFileAttributes(strFilePath.c_str(), 
           FILE_ATTRIBUTE_NORMAL) == FALSE) 
      return ::GetLastError(); 

      // Delete file 
      if(::DeleteFile(strFilePath.c_str()) == FALSE) 
      return ::GetLastError(); 
     } 
     } 
    } while(::FindNextFile(hFile, &FileInformation) == TRUE); 

    // Close handle 
    ::FindClose(hFile); 

    DWORD dwError = ::GetLastError(); 
    if(dwError != ERROR_NO_MORE_FILES) 
     return dwError; 
    else 
    { 
     if(!bSubdirectory) 
     { 
     // Set directory attributes 
     if(::SetFileAttributes(refcstrRootDirectory.c_str(), 
           FILE_ATTRIBUTE_NORMAL) == FALSE) 
      return ::GetLastError(); 

     // Delete directory 
     if(::RemoveDirectory(refcstrRootDirectory.c_str()) == FALSE) 
      return ::GetLastError(); 
     } 
    } 
    } 

    return 0; 
} 


int main() 
{ 
    int   iRC     = 0; 
    std::string strDirectoryToDelete = "c:\\mydir"; 


    // Delete 'c:\mydir' without deleting the subdirectories 
    iRC = DeleteDirectory(strDirectoryToDelete, false); 
    if(iRC) 
    { 
    std::cout << "Error " << iRC << std::endl; 
    return -1; 
    } 

    // Delete 'c:\mydir' and its subdirectories 
    iRC = DeleteDirectory(strDirectoryToDelete); 
    if(iRC) 
    { 
    std::cout << "Error " << iRC << std::endl; 
    return -1; 
    } 

    // Wait for keystroke 
    _getch(); 

    return 0; 
} 

來源:http://www.codeguru.com/forum/showthread.php?t=239271

+4

感謝您發佈不是Boost或調用system()的東西。 – 2013-02-07 20:48:18

+0

但有一天,鏈接將會死亡。你打算在答案中包含相關的代碼嗎? – jogojapan 2013-02-26 08:56:41

+0

看起來像這個解決方案可能由於文件系統競爭而失敗:DeleteFile不是原子的,這意味着刪除包含它的目錄可能會失敗,因爲該目錄尚未(尚未)爲空。本講座詳細解釋了此問題,並提供了一種更安全的方法來刪除Windows上的目錄/樹:https://www.youtube.com/watch?v=uhRWMGBjlO8 – 2018-03-02 19:28:55

0

//對於Windows:

#include <direct.h> 


if(_rmdir("FILEPATHHERE") != -1) 
{ 
    //success  
} else { 
    //failure 
} 
5

使用SHFileOperation刪除的文件夾recursivelly

2

你也可以試試這個,如果你是在Linux上:

system("rm -r path"); 
0

嘗試利用系統 「rmdir -s -q file_to_delte」 。
這將刪除文件夾及其中的所有文件。

3
void remove_dir(char *path) 
{ 
     struct dirent *entry = NULL; 
     DIR *dir = NULL; 
     dir = opendir(path); 
     while(entry = readdir(dir)) 
     { 
       DIR *sub_dir = NULL; 
       FILE *file = NULL; 
       char abs_path[100] = {0}; 
       if(*(entry->d_name) != '.') 
       { 
         sprintf(abs_path, "%s/%s", path, entry->d_name); 
         if(sub_dir = opendir(abs_path)) 
         { 
           closedir(sub_dir); 
           remove_dir(abs_path); 
         } 
         else 
         { 
           if(file = fopen(abs_path, "r")) 
           { 
             fclose(file); 
             remove(abs_path); 
           } 
         } 
       } 
     } 
     remove(path); 
} 
0

我自己的基於hB0的實現,它還允許您查看每個文件夾中的文件數量,並且性能略有提升。

#include <string> 
#include <iostream> 
#include <cstdlib> 
#include <cstdio> 
#include <windows.h> 
#include <conio.h> 

union seperated { 
    struct { 
    unsigned int low; 
    unsigned int high; 
    } uint; 
    unsigned long long ull; 
}; 

unsigned long long num_dirs = 1; 
unsigned long long num_files = 0; 
seperated size_files; 

int DeleteDirectory(char* refRootDirectory);  //predeclare it 

int DeleteDirectory(char* refRootDirectory) { 
    HANDLE  hFile;    // Handle to directory 
    std::string strFilePath;   // Filepath 
    WIN32_FIND_DATA FileInformation; // File information 
    int  dwError;   // Folder deleting error 
    std::string strPattern;   // Pattern 

    strPattern = (std::string)(refRootDirectory) + "\\*.*"; 
    hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation); 

    if(hFile != INVALID_HANDLE_VALUE) 
    { 
     do { 
      if(FileInformation.cFileName[0] != '.') { 
       strFilePath.erase(); 
       strFilePath = std::string(refRootDirectory) + "\\" + FileInformation.cFileName; 

       if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 
        DeleteDirectory((char*)strFilePath.c_str()); 

        dwError = ::GetLastError(); 
        if(dwError != ERROR_NO_MORE_FILES) { 
         std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
         return dwError; 
        } else { 
         // Set directory attributes 
         if(! ::SetFileAttributes(refRootDirectory,FILE_ATTRIBUTE_NORMAL)) { 
          std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
          return ::GetLastError(); 
         } 

         // Delete directory 
         if(! ::RemoveDirectory(refRootDirectory)) { 
          std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
          return ::GetLastError(); 
         } 
        } 

        ++num_dirs; 
       } else { 

        // Set file attributes 
        if(! ::SetFileAttributes(strFilePath.c_str(),FILE_ATTRIBUTE_NORMAL)) { 
         std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
         return ::GetLastError(); 
        } 

        // Delete file 
        if (! ::DeleteFile(strFilePath.c_str())) { 
         std::cout << "!ERROR!: [[" << strFilePath.c_str() << "]]\n"; 
         return ::GetLastError(); 
        } 

        size_files.ull  += FileInformation.nFileSizeLow; 
        size_files.uint.high += FileInformation.nFileSizeHigh; 

        ++num_files; 
       } 
      } 
     } while(::FindNextFile(hFile,&FileInformation)); 

     // Close handle 
     ::FindClose(hFile ); 
    } 

    return 0; 
} 

unsigned long long num_files_total=0; 
unsigned long long num_dirs_total=0; 
unsigned long long total_size_files=0; 

void my_del_directory(char* dir_name) { 
    int iRC = DeleteDirectory(dir_name); 
    //int iRC=0; 

    std::cout << "\"" << dir_name << "\"" 
      "\n Folders: " << num_dirs 
      << "\n Files: " << num_files 
      << "\n Size: " << size_files.ull << " Bytes"; 
    if(iRC) 
    { 
     std::cout << "\n!ERROR!: " << iRC; 
    } 
    std::cout << "\n\n"; 

    num_dirs_total += num_dirs; 
    num_files_total += num_files; 
    total_size_files += size_files.ull; 
    num_dirs = 1; 
    num_files = 0; 
    size_files.ull = 0ULL; 
    return; 
} 

int main(void) 
{ 
    size_files.ull = 0ULL; 

    my_del_directory((char*)"C:\Windows\temp"  ); 
     // This will clear out the System temporary directory on windows systems 

    std::cout << "\n\nResults" << "\nTotal Folders: " << num_dirs_total 
        << "\nTotal Files: " << num_files_total 
        << "\nTotal Size: " << total_size_files << " Bytes\n"; 

    return 0; 
} 
3

用C++ 17可以使用std::filesystem,在C++ 14 std::experimental::filesystem已經可用。兩者都允許使用filesystem::remove()

C++ 17:

#include <filesystem> 
std::filesystem::path::remove("myEmptyDirectoryOrFile"); // Deletes empty directories or single files. 
std::filesystem::path::remove_all("myDirectory"); // Deletes one or more files recursively. 

C++ 14:

#include <experimental/filesystem> 
std::experimental::filesystem::path::remove("myDirectory"); 

注1: 這些功能在錯誤的情況下拋出filesystem_error。如果要避免捕捉異常,請使用std::error_code的重載變量作爲第二個參數。例如。

std::error_code errorCode; 
if (!std::filesystem::path::remove("myEmptyDirectoryOrFile", errorCode)) { 
    std::cout << errorCode.message() << std::endl; 
} 

注2: 轉換到std::filesystem::path發生從不同的編碼隱式的,所以你可以通過字符串filesystem::remove()