2008-10-05 180 views
62

我試圖顯示在所選目錄(以及可選的任何子目錄)中找到的所有文件的列表。我遇到的問題是,當GetFiles()方法遇到無法訪問的文件夾時,它會引發異常並停止進程。當Directory.GetFiles()被拒絕訪問時忽略文件夾/文件

如何忽略此異常(並忽略受保護的文件夾/文件)並繼續向列表中添加可訪問的文件?

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

另一個(標記爲重複)的問題 - http://stackoverflow.com/questions/1393178/unauthorizedaccessexception-cannot-resolve-directory-getfiles-failure?noredirect=1 – 2016-04-19 22:30:40

回答

42

您將不得不手動遞歸;不要使用AllDirectories - 一次查看一個文件夾,然後嘗試從子目錄中獲取文件。未經測試,但類似下面(注意使用代表而不是構建陣列):

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

太好了,我還沒有發現類似的東西這在VB.NET中。希望你不介意,如果我[在VB.NET這裏翻譯](http://stackoverflow.com/a/34924036/1197518) – Steve 2016-01-21 19:31:18

+3

仍然不夠:當文件夾中只有一個文件無法訪問時,GetFiles會在內部拋出。所以整個文件夾將不被處理。 – 2016-11-24 08:15:10

2

這應該回答這個問題。我忽略了通過子目錄的問題,我假設你已經明白了。

當然,您不需要爲此提供單獨的方法,但是您可能會發現它也是驗證路徑有效的有用位置,並處理調用GetFiles時可能遇到的其他異常( )。

希望這會有所幫助。

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

有關處理UnauthorisedAccessException問題的解決方案,請參閱https://stackoverflow.com/a/10728792/89584

如果對GetFiles()或GetDirectories()的任何調用位於具有權限混合的文件夾中,上述所有解決方案都將會丟失文件和/或目錄。

+1

涉及GetFiles/GetDirectories的所有解決方案都必然存在相同的問題,並且因此有點不雅 – 2014-12-30 09:54:47

2

我知道這個問題有點舊,但我今天也遇到了同樣的問題,我發現下面的文章詳細解釋了「文件夾遞歸」解決方案。

的製品確認GetDirectories()方法的缺陷...:

不幸的是,此[使用GetDirectories()方法]有問題。其中的關鍵是您嘗試讀取的文件夾中的某些文件可能被配置,以致當前用戶可能無法訪問它們。該方法拋出 UnauthorizedAccessException,而不是將文件夾忽略爲 。但是,我們可以通過創建我們自己的遞歸文件夾搜索代碼來繞過這個問題 。

...然後詳細介紹瞭解決方案:

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

+0

最容易實現在我的要求。 – 2017-12-06 08:59:05

12

這個簡單的功能運作良好,並符合要求的問題。

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; 
} 
3

一個簡單的方法是使用文件列表和目錄的隊列。 它節省了記憶。 如果使用遞歸程序執行相同的任務,則可能會導致OutOfMemory異常。 輸出:列表中添加的文件按照從上到下(寬度優先)目錄樹進行組織。

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; 
} 

步驟:

  1. 排入根隊列
  2. 在一個循環中,出列,添加文件在目錄列表,和子文件夾添加到隊列中。
  3. 重複直到隊列爲空。