Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerating Files Throwing Exception

Tags:

c#

file

I am trying to enumerate through files on my computer using the below code but everytime it hits a file or dir that I don't have permission to read it throws an exception. Is there any way I can continue searching after the exception has been thrown? I know some people have had similar issues but is there any other way of doing this other than checking every file/folder individually?

try
{
    string[] files = Directory.GetFiles(@"C:\", "*.*",SearchOption.AllDirectories);
    foreach (string file in files)
    {
        Console.WriteLine(file);
    }
}
catch
{
}

Thanks for any help as this is driving me mad!

like image 563
Bali C Avatar asked Oct 13 '11 15:10

Bali C


People also ask

What does it mean to enumerate files?

EnumerateFiles(String, String, EnumerationOptions) Returns an enumerable collection of full file names that match a search pattern and enumeration options in a specified path, and optionally searches subdirectories. EnumerateFiles(String) Returns an enumerable collection of full file names in a specified path.

How to handle task exception?

Exceptions are propagated when you use one of the static or instance Task. Wait methods, and you handle them by enclosing the call in a try / catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.

How to throw exception in task c#?

try { t. Start(); await t; } catch (Exception e) { // When awating on the task, the exception itself is thrown. // in this case a regular Exception. } } In TPL, When throwing an exception inside a Task, it's wrapped with an AggregateException.


1 Answers

I came across the same problem just today. I hacked together the following code. If you want to use it in a real product you might need to improve the error handling. Since this was for a one-shot script I didn't care much.

static IEnumerable<string> EnumerateFilesRecursive(string root,string pattern="*")
{
    var todo = new Queue<string>();
    todo.Enqueue(root);
    while (todo.Count > 0)
    {
        string dir = todo.Dequeue();
        string[] subdirs = new string[0];
        string[] files = new string[0];
        try
        {
            subdirs = Directory.GetDirectories(dir);
            files = Directory.GetFiles(dir, pattern);
        }
        catch (IOException)
        {
        }
        catch (System.UnauthorizedAccessException)
        {
        }

        foreach (string subdir in subdirs)
        {
            todo.Enqueue(subdir);
        }
        foreach (string filename in files)
        {
            yield return filename;
        }
    }
}

To use it you can either:

string[] files = EnumerateFilesRecursive(@"C:\").ToArray();//Note the ToArray()
foreach (string file in files)
{
   Console.WriteLine(file);
}

which first enumerates all files, stores all file names in memory and only then displays them. Alternatively you can:

IEnumerable<string> files = EnumerateFilesRecursive(@"C:\");//Note that there is NO ToArray()
foreach (string file in files)
{
   Console.WriteLine(file);
}

Which writes while enumerating and thus doesn't need to keep all filenames in memory at the same time.

like image 135
CodesInChaos Avatar answered Oct 13 '22 00:10

CodesInChaos