2008-10-05 29 views
62

Tôi đang cố gắng hiển thị danh sách tất cả các tệp được tìm thấy trong thư mục đã chọn (và tùy chọn bất kỳ thư mục con nào). Vấn đề tôi gặp phải là khi phương thức GetFiles() đi qua một thư mục mà nó không thể truy cập, nó ném một ngoại lệ và quá trình dừng lại.Bỏ qua các thư mục/tệp khi Directory.GetFiles() bị từ chối truy cập

Làm cách nào để bỏ qua ngoại lệ này (và bỏ qua thư mục/tệp được bảo vệ) và tiếp tục thêm tệp có thể truy cập vào danh sách?

try 
{ 
    if (cbSubFolders.Checked == false) 
    { 
     string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath); 
     foreach (string fileName in files) 
      ProcessFile(fileName); 
    } 
    else 
    { 
     string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories); 
     foreach (string fileName in files) 
      ProcessFile(fileName); 
    } 
    lblNumberOfFilesDisplay.Enabled = true; 
} 
catch (UnauthorizedAccessException) { } 
finally {} 
+0

khác (đánh dấu là trùng lặp) câu hỏi - http://stackoverflow.com/questions/1393178/unauthorizedaccessexception-cannot-resolve-directory-getfiles-failure?noredirect=1 –

Trả lời

42

Bạn sẽ phải thực hiện thao tác đệ quy theo cách thủ công; không sử dụng AllDirectories - tìm một thư mục tại một thời điểm, sau đó thử lấy các tệp từ thư mục con. Chưa được kiểm tra, nhưng giống như dưới đây (lưu ý sử dụng một đại biểu thay vì xây dựng một mảng):

using System; 
using System.IO; 
static class Program 
{ 
    static void Main() 
    { 
     string path = ""; // TODO 
     ApplyAllFiles(path, ProcessFile); 
    } 
    static void ProcessFile(string path) {/* ... */} 
    static void ApplyAllFiles(string folder, Action<string> fileAction) 
    { 
     foreach (string file in Directory.GetFiles(folder)) 
     { 
      fileAction(file); 
     } 
     foreach (string subDir in Directory.GetDirectories(folder)) 
     { 
      try 
      { 
       ApplyAllFiles(subDir, fileAction); 
      } 
      catch 
      { 
       // swallow, log, whatever 
      } 
     } 
    } 
} 
+0

Quá tốt, tôi đã không tìm thấy bất cứ điều gì như điều này trong VB.NET. Hy vọng bạn không phiền nếu tôi có [dịch này trong VB.NET ở đây] (http://stackoverflow.com/a/34924036/1197518) – Steve

+3

vẫn chưa đủ: GetFiles ném nội bộ khi chỉ có một tập tin là không thể truy cập trong một thư mục . Vì vậy toàn bộ thư mục sẽ không được xử lý. –

2

Điều này sẽ trả lời câu hỏi. Tôi đã bỏ qua vấn đề đi qua các thư mục con, tôi giả sử bạn đã tìm ra điều đó. Tất nhiên, bạn không cần phải có một phương pháp riêng biệt cho việc này, nhưng bạn có thể thấy nó là một nơi hữu ích để xác minh đường dẫn hợp lệ và xử lý các ngoại lệ khác mà bạn có thể gặp phải khi gọi GetFiles ().

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

private string[] GetFiles(string path) 
{ 
    string[] files = null; 
    try 
    { 
     files = Directory.GetFiles(path); 
    } 
    catch (UnauthorizedAccessException) 
    { 
     // might be nice to log this, or something ... 
    } 

    return files; 
} 

private void Processor(string path, bool recursive) 
{ 
    // leaving the recursive directory navigation out. 
    string[] files = this.GetFiles(path); 
    if (null != files) 
    { 
     foreach (string file in files) 
     { 
      this.Process(file); 
     } 
    } 
    else 
    { 
     // again, might want to do something when you can't access the path? 
    } 
} 
1

xem https://stackoverflow.com/a/10728792/89584 để biết giải pháp xử lý vấn đề UnauthorisedAccessException.

Tất cả các giải pháp ở trên sẽ bỏ lỡ tệp và/hoặc thư mục nếu có bất kỳ lệnh gọi tới GetFiles() hoặc GetDirectories() nào nằm trong thư mục có kết hợp quyền.

+1

tất cả các giải pháp liên quan đến GetFiles/GetDirectories đều có cùng vấn đề và do đó, một chút không phù hợp –

2

Tôi biết câu hỏi này hơi cũ, nhưng hôm nay tôi đã gặp vấn đề tương tự và tôi đã tìm thấy bài viết sau giải thích chi tiết về 'đệ quy thư mục'.

Bài báo thừa nhận những sai sót của phương pháp GetDirectories() ...:

Thật không may, điều này [sử dụng GetDirectories() phương pháp] có vấn đề. Chính trong số đó là một số các thư mục mà bạn cố gắng đọc có thể được định cấu hình để người dùng hiện tại không thể truy cập chúng. Thay vì bỏ qua các thư mục đến mà bạn có quyền truy cập bị giới hạn, phương thức sẽ ném ra một Ngoại lệ thừa nhận ngoại lệ. Tuy nhiên, chúng tôi có thể giải quyết vấn đề này bằng cách tạo mã tìm kiếm thư mục đệ quy của riêng chúng tôi.

... và sau đó giới thiệu các giải pháp một cách chi tiết:

http://www.blackwasp.co.uk/FolderRecursion.aspx

+0

Dễ nhất để thực hiện theo yêu cầu của tôi. –

12

chức năng đơn giản này hoạt động tốt và đáp ứng các yêu cầu câu hỏi.

private List<string> GetFiles(string path, string pattern) 
{ 
    var files = new List<string>(); 

    try 
    { 
     files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)); 
     foreach (var directory in Directory.GetDirectories(path)) 
      files.AddRange(GetFiles(directory, pattern)); 
    } 
    catch (UnauthorizedAccessException) { } 

    return files; 
} 
+0

Đó là cách phức tạp và minh bạch nhất để làm điều đó (y) – derFunk

+6

Thật không may nó dừng lại trên ngoại lệ đầu tiên ... –

+1

Có, vì việc xử lý lỗi còn thiếu, nó không được sử dụng nhiều. Chỉ cần cố gắng tìm kiếm toàn bộ c: \ tree. Có một số khu vực trong hệ thống tệp Windows nơi người dùng có thể ngay cả với quyền quản trị không có đủ quyền truy cập. Đó là những gì thách thức chính là tất cả về ở đây (bên cạnh các điểm giao nhau, và như vậy). – Philm

3

Cách đơn giản để thực hiện việc này là sử dụng Danh sách tệp và Hàng đợi cho thư mục. Nó bảo tồn bộ nhớ. Nếu bạn sử dụng một chương trình đệ quy để thực hiện tác vụ tương tự, điều đó có thể ném ngoại lệ OutOfMemory. Đầu ra: các tệp được thêm vào trong Danh sách, được sắp xếp theo cây thư mục trên cùng (dưới cùng).

public static List<string> GetAllFilesFromFolder(string root, bool searchSubfolders) { 
    Queue<string> folders = new Queue<string>(); 
    List<string> files = new List<string>(); 
    folders.Enqueue(root); 
    while (folders.Count != 0) { 
     string currentFolder = folders.Dequeue(); 
     try { 
      string[] filesInCurrent = System.IO.Directory.GetFiles(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); 
      files.AddRange(filesInCurrent); 
     } 
     catch { 
      // Do Nothing 
     } 
     try { 
      if (searchSubfolders) { 
       string[] foldersInCurrent = System.IO.Directory.GetDirectories(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); 
       foreach (string _current in foldersInCurrent) { 
        folders.Enqueue(_current); 
       } 
      } 
     } 
     catch { 
      // Do Nothing 
     } 
    } 
    return files; 
} 

bước:

  1. Enqueue gốc trong hàng đợi
  2. Trong một vòng lặp, Dequeue nó, Thêm các tập tin trong thư mục đó vào danh sách, và Thêm thư mục con vào hàng đợi.
  3. Lặp lại cho đến khi hàng đợi trống.
Các vấn đề liên quan