2008-10-05 255 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. 重复直到队列为空。