Ignore folders/files when Directory.GetFiles() is

2018-12-31 08:26发布

I am trying to display a list of all files found in the selected directory (and optionally any subdirectories). The problem I am having is that when the GetFiles() method comes across a folder that it cannot access, it throws an exception and the process stops.

How do I ignore this exception (and ignore the protected folder/file) and continue adding accessible files to the list?

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

标签: c# getfiles
8条回答
永恒的永恒
2楼-- · 2018-12-31 08:58

A simple way to do this is by using a List for files and a Queue for directories. It conserves memory. If you use a recursive program to do the same task, that could throw OutOfMemory exception. The output: files added in the List, are organised according to the top to bottom (breadth first) directory tree.

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

Steps:

  1. Enqueue the root in the queue
  2. In a loop, Dequeue it, Add the files in that directory to the list, and Add the subfolders to the queue.
  3. Repeat untill the queue is empty.
查看更多
孤独总比滥情好
3楼-- · 2018-12-31 08:59

You will have to do the recursion manually; don't use AllDirectories - look one folder at a time, then try getting the files from sub-dirs. Untested, but something like below (note uses a delegate rather than building an array):

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
            }
        }
    }
}
查看更多
后来的你喜欢了谁
4楼-- · 2018-12-31 09:03

This simple function works well and meets the questions requirements.

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;
}
查看更多
旧时光的记忆
5楼-- · 2018-12-31 09:08

This should answer the question. I've ignored the issue of going through subdirectories, I'm assuming you have that figured out.

Of course, you don't need to have a seperate method for this, but you might find it a useful place to also verify the path is valid, and deal with the other exceptions that you could encounter when calling GetFiles().

Hope this helps.

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?
    }
}
查看更多
荒废的爱情
6楼-- · 2018-12-31 09:09

I know this question is somewhat old, but I had this same problem today and I found the following article that explains a 'folder recursion' solution in detail.

The article acknowledges the flaws of the GetDirectories() method... :

Unfortunately, this [using the GetDirectories() method] has problems. Key amongst these is that some of the folders that you attempt to read could be configured so that the current user may not access them. Rather than ignoring folders to which you have restricted access, the method throws an UnauthorizedAccessException. However, we can circumvent this problem by creating our own recursive folder search code.

... and then introduces the solution in detail:

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

查看更多
登录 后发表回答