2012-03-23 48 views

Trả lời

4

Nếu bạn đã sẵn sàng sử dụng API Windows thì cách dễ nhất để thực hiện việc này là gọi SHFileOperation. Sử dụng thao tác FO_DELETE và đừng quên để tăng gấp đôi null-chấm dứt tên thư mục của bạn.

+0

Hãy nhớ rằng SHFileOperation hoạt động tốt cho các ứng dụng Chế độ người dùng nhưng không hoạt động khi được gọi từ Dịch vụ Windows, đặc biệt nếu Mạo danh đang được sử dụng để xóa thư mục trên mạng chia sẻ UNC. Đối với kịch bản này, bạn sẽ cần phải làm công việc grunt và sử dụng FindFirstFile()/FindNext() với DeleteFile()/RemoveDirectory() cách cứng – WebDrive

3

Thông thường, nếu không có phương thức thư viện nào, điều này được thực hiện bằng cách đệ quy. Một hàm lặp lại tất cả các mục nhập thư mục, xóa các tệp 'bình thường' và tự gọi nó bằng bất kỳ đường dẫn thư mục nào được tìm thấy. Điều này phá hủy toàn bộ cây thư mục, (phiên bản Windows của tôi đã kiểm tra rõ ràng trên đường dẫn được thông qua để ngăn chặn nó phá hủy các thư mục hệ điều hành trong trường hợp vô tình đi qua trong một tham số tự tử).

2

Đây có thể là khập khiễng, nhưng hãy cân nhắc sử dụng

system("rd /s /q ..."); 

Nó xấu xí, nhưng nó quá đơn giản để bỏ qua. Nó cũng có tất cả các "làm thế nào để đối phó với các tập tin trên mạng chia sẻ" công cụ làm việc ra ngoài. Bất kỳ giải pháp nào bạn đưa ra có thể là việc thực hiện lại (không đầy đủ và/hoặc không chính xác) của rd, vì vậy, hãy gọi ra quy trình bên ngoài thực sự sẽ là sử dụng lại mã tốt đẹp. ;-)

+0

Tái sử dụng mã và không thể xuất hiện với thậm chí không biên dịch lỗi nếu rd không tồn tại . Đối với một chương trình rất nhỏ, điều này có thể hữu ích và đúng, đối với những người lớn tuổi thọ lớn, ít hơn. Cá nhân, tôi sẽ luôn kiểm tra xem lệnh đó có tồn tại không. –

+0

@phresnel: Câu hỏi chỉ dành cho các hệ thống Windows, và 'rd' có sẵn trên tất cả các hệ thống Windows theo mặc định. Tôi muốn đi ra ngoài một chi và tuyên bố rằng 'thứ' đang có sẵn có nhiều khả năng hơn 'SHFileOperation' đang có sẵn (' SHFileOperation' chỉ tồn tại từ Windows XP, và nó đã không được chấp nhận với Windows Vista). –

+0

Xác suất ít liên quan đến tôi. Cá nhân, tôi không phải là một lỗi thời gian biên dịch nếu một số chức năng không có; với hệ thống bạn chưa bao giờ có lỗi biên dịch thời gian. Như đã nói, đối với các chương trình nhỏ, hệ thống cụ thể, điều này có thể không sao. Nhưng tôi sẽ tư vấn chống lại nó cho các chương trình lớn hơn hoặc sống lâu. Bạn không bao giờ biết những gì trong 5, 10, 15 năm kể từ bây giờ. Nếu đột nhiên mọi người sẽ chuyển sang Mac hoặc Linux, thì chắc chắn bạn cũng sẽ muốn con bò tiền mặt của bạn chạy trên nền tảng đó. –

7

Giải pháp tốt nhất, nếu bạn có thể sử dụng, là boost::filesystem::remove_all. Bằng cách đó, bạn không phải lo lắng về nền tảng cụ thể. Tôi không biết về bất kỳ giải pháp độc lập nền tảng nào khác; cách thông thường khác sẽ liên quan đến việc đọc thư mục, và đệ quy giảm dần nó (nhưng cách đọc thư mục cũng sử dụng boost::filesystem hoặc mã phụ thuộc hệ thống).

2

Theo MSDN, SHFileOperation không phải là luồng an toàn khi được sử dụng với đường dẫn tương đối. Nó chỉ có thể được sử dụng một cách an toàn với đường dẫn tuyệt đối.

tôi khuyên bạn nên sử dụng mã này để thay thế:

double directory_delete(char *pathname) 
{ 
    string str(pathname); 
    if (!str.empty()) 
    { 
     while (*str.rbegin() == '\\' || *str.rbegin() == '/') 
     { 
      str.erase(str.size()-1); 
     } 
    } 
    replace(str.begin(),str.end(),'/','\\'); 

    struct stat sb; 
    if (stat((char *)str.c_str(),&sb) == 0 && 
     S_ISDIR(sb.st_mode)) 
    { 
      HANDLE hFind; 
      WIN32_FIND_DATA FindFileData; 

      TCHAR DirPath[MAX_PATH]; 
      TCHAR FileName[MAX_PATH]; 

      _tcscpy(DirPath,(char *)str.c_str()); 
      _tcscat(DirPath,"\\*"); 
      _tcscpy(FileName,(char *)str.c_str()); 
      _tcscat(FileName,"\\"); 

      hFind = FindFirstFile(DirPath,&FindFileData); 
      if (hFind == INVALID_HANDLE_VALUE) return 0; 
      _tcscpy(DirPath,FileName); 

      bool bSearch = true; 
      while (bSearch) 
      { 
       if (FindNextFile(hFind,&FindFileData)) 
       { 
        if (!(_tcscmp(FindFileData.cFileName,".") && 
         _tcscmp(FindFileData.cFileName,".."))) continue; 
        _tcscat(FileName,FindFileData.cFileName); 
        if ((FindFileData.dwFileAttributes & 
        FILE_ATTRIBUTE_DIRECTORY)) 
        { 
         if (!directory_delete(FileName)) 
         { 
          FindClose(hFind); 
          return 0; 
         } 
         RemoveDirectory(FileName); 
         _tcscpy(FileName,DirPath); 
        } 
        else 
        { 
         if (FindFileData.dwFileAttributes & 
          FILE_ATTRIBUTE_READONLY) 
          _chmod(FileName, _S_IWRITE); 

         if (!DeleteFile(FileName)) 
         { 
          FindClose(hFind); 
          return 0; 
         } 
         _tcscpy(FileName,DirPath); 
        } 
       } 
       else 
       { 
        if (GetLastError() == ERROR_NO_MORE_FILES) 
         bSearch = false; 
        else 
        { 
         FindClose(hFind); 
         return 0; 
        } 
       } 
      } 
      FindClose(hFind); 

      return (double)(RemoveDirectory((char *)str.c_str()) == true); 
    } 
    else 
    { 
     return 0; 
    } 
} 

Nếu bạn muốn sử dụng mã của tôi "như-là", bạn sẽ cần những tiêu đề và như vậy ở phía trên cùng của tập tin cpp của bạn:

#include <windows.h> // winapi 
#include <sys/stat.h> // stat 
#include <tchar.h> // _tcscpy,_tcscat,_tcscmp 
#include <string> // string 
#include <algorithm> // replace 

using namespace std; 

... và tôi nghĩ vậy.

Mã của tôi được dựa trên bài viết này:

http://www.codeguru.com/cpp/w-p/files/folderdirectorymaintenance/article.php/c8999/Deleting-a-Directory-Along-with-SubFolders.htm

tôi khuyên các bạn không bao giờ sử dụng SHFileOperation, ngoài vấn đề an toàn, nó được thay thế bởi IFileOperation kể từ Windows Vista.

Hy vọng điều này sẽ hữu ích!

Các vấn đề liên quan