Ignore folders/files when Directory.GetFiles() is denied access

前端 未结 8 1847
余生分开走
余生分开走 2020-11-22 04:27

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 co

相关标签:
8条回答
  • 2020-11-22 05:03

    Here's a full-featured, .NET 2.0-compatible implementation.

    You can even alter the yielded List of files to skip over directories in the FileSystemInfo version!

    (Beware null values!)

    public static IEnumerable<KeyValuePair<string, string[]>> GetFileSystemInfosRecursive(string dir, bool depth_first)
    {
        foreach (var item in GetFileSystemObjectsRecursive(new DirectoryInfo(dir), depth_first))
        {
            string[] result;
            var children = item.Value;
            if (children != null)
            {
                result = new string[children.Count];
                for (int i = 0; i < result.Length; i++)
                { result[i] = children[i].Name; }
            }
            else { result = null; }
            string fullname;
            try { fullname = item.Key.FullName; }
            catch (IOException) { fullname = null; }
            catch (UnauthorizedAccessException) { fullname = null; }
            yield return new KeyValuePair<string, string[]>(fullname, result);
        }
    }
    
    public static IEnumerable<KeyValuePair<DirectoryInfo, List<FileSystemInfo>>> GetFileSystemInfosRecursive(DirectoryInfo dir, bool depth_first)
    {
        var stack = depth_first ? new Stack<DirectoryInfo>() : null;
        var queue = depth_first ? null : new Queue<DirectoryInfo>();
        if (depth_first) { stack.Push(dir); }
        else { queue.Enqueue(dir); }
        for (var list = new List<FileSystemInfo>(); (depth_first ? stack.Count : queue.Count) > 0; list.Clear())
        {
            dir = depth_first ? stack.Pop() : queue.Dequeue();
            FileSystemInfo[] children;
            try { children = dir.GetFileSystemInfos(); }
            catch (UnauthorizedAccessException) { children = null; }
            catch (IOException) { children = null; }
            if (children != null) { list.AddRange(children); }
            yield return new KeyValuePair<DirectoryInfo, List<FileSystemInfo>>(dir, children != null ? list : null);
            if (depth_first) { list.Reverse(); }
            foreach (var child in list)
            {
                var asdir = child as DirectoryInfo;
                if (asdir != null)
                {
                    if (depth_first) { stack.Push(asdir); }
                    else { queue.Enqueue(asdir); }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 05:06

    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
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题