Finding files: Recursion vs Stack<>…FIGHT!

I was just poking around the Internet and came across a blog post highlighting a solution to a common problem: find all files matching a criteria (e.g. *.dll) from a folder and all its subfolders (e.g. c:\windows and all subdirectories). In this post, I compare the speed of two methods using code in C#.

Method 1 involves recursion. I saw a sample at http://www.gfilter.net/default.aspx?Post=Code-Snippet-of-the-Day%3a-Recursive-File-Finder and MSDN.

Method 2 involves using a stack to process subdirectories in a Last in, first out manner.  I saw this from http://dotnetperls.com/Content/Recursively-Find-Files.aspx.

The result from finding all 13,300+ DLLs in c:\windows and all subdirectories:

FileFinderRecursive Elapsed: 6876ms.
FileFinderStack Elapsed: 5725ms.

The stack method was almost 20% faster.

Here’s some code from a quick C# console app I just wrote to compare the two:

class Program
{
    static void Main(string[] args)
    {
        Stopwatch s;
        IFinder finder;
        string startDir = @"c:\windows";
        string matchType = "*.dll";

        //Test Recursion method
        s = Stopwatch.StartNew();
        finder = new FileFinderRecursive();
        var filesRecursive = finder.Find(startDir, matchType);
        s.Stop();
        Console.WriteLine("FileFinderRecursive Elapsed: " + s.ElapsedMilliseconds + "ms.");

        //Test Stack method
        s = Stopwatch.StartNew();
        finder = new FileFinderStack();
        var filesStack = finder.Find(startDir, matchType);
        s.Stop();
        Console.WriteLine("FileFinderStack Elapsed: " + s.ElapsedMilliseconds + "ms.");    

        Console.Read();
    }
}
public interface IFinder
{
    List<FileInfo> Find(string startDir, string matchType);
}

/// <summary>
/// Recursively finds a list of files that match the specified critiria
/// </summary>
public class FileFinderRecursive : IFinder
{
    private Dictionary<FileInfo, int> files;

    public List<FileInfo> Find(string startDir, string matchType)
    {
        files = new Dictionary<FileInfo, int>();
        findFiles(startDir, matchType);

        return files.Keys.ToList();
    }

    private void findFiles(string startDir, string matchType)
    {
        DirectoryInfo d = new DirectoryInfo(startDir);
        FileInfo[] fileInfos;
        try
        {
            fileInfos = d.GetFiles(matchType);
        }
        catch
        {
            return; //most likely Access Exception.  BAIL!
        }
        foreach (FileInfo f in fileInfos)
        {
            if (!files.ContainsKey(f))
            {
                files.Add(f, 0);
            }
        }

        if (d.GetDirectories().Length > 0)
        {
            foreach (DirectoryInfo subD in d.GetDirectories())
            {
                findFiles(subD.FullName, matchType);
            }
        }
    }
}

/// <summary>
/// Finds a list of files that match the specified criteria using a stack
/// </summary>
public class FileFinderStack : IFinder
{
    public List<FileInfo> Find(string startDir, string matchType)
    {
        DirectoryInfo dirStart = new DirectoryInfo(startDir);
        List<FileInfo> result = new List<FileInfo>();
        Stack<DirectoryInfo> stack = new Stack<DirectoryInfo>();
        stack.Push(dirStart);
        while (stack.Count > 0)
        {
            DirectoryInfo dir = stack.Pop();
            try
            {
                result.AddRange(dir.GetFiles(matchType));
                DirectoryInfo[] subDirs = dir.GetDirectories();
                foreach (DirectoryInfo dn in subDirs)
                {
                    stack.Push(dn);
                }
            }
            catch { }
        }
        return result;
    }
}
This entry was posted on Sunday, June 7th, 2009 at 12:22 am and is filed under Programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Related Posts

One Response to “Finding files: Recursion vs Stack<>…FIGHT!”

  1. afdsa

Leave a Reply