代码之家  ›  专栏  ›  技术社区  ›  Rowan

拒绝访问目录.GetFiles()时忽略文件夹/文件

  •  68
  • Rowan  · 技术社区  · 16 年前

    我试图显示在所选目录(以及任意子目录)中找到的所有文件的列表。我遇到的问题是,当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 {}
    
    8 回复  |  直到 11 年前
        1
  •  48
  •   Marc Gravell    16 年前

    您必须手动执行递归;不要使用所有目录-一次查看一个文件夹,然后尝试从子目录获取文件。未测试,但如下所示(注意使用委托而不是构建数组):

    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
                }
            }
        }
    }
    
        2
  •  14
  •   Ben Gripka Javed Akram    4 年前

    private List<string> GetFiles(string path, string pattern)
    {
        var files = new List<string>();
        var directories = new string[] { };
    
        try
        {
            files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly));
            directories = Directory.GetDirectories(path);
        }
        catch (UnauthorizedAccessException) { }
    
        foreach (var directory in directories)
            try
            {
                files.AddRange(GetFiles(directory, pattern));
            }
            catch (UnauthorizedAccessException) { }
    
        return files;
    }
    
        3
  •  10
  •   Shahin Dohan    4 年前

    自.NET标准2.1以来,您现在只需执行以下操作:

    var filePaths = Directory.EnumerateFiles(@"C:\my\files", "*.xml", new EnumerationOptions
    {
        IgnoreInaccessible = true,
        RecurseSubdirectories = true
    });
    

    MSDN docs 关于

    获取或设置一个值,该值指示在拒绝访问时是否跳过文件或目录(例如UnauthorizedAccessException或SecurityException)。默认值为true。

    默认值实际上是true,但我将其保留在这里只是为了显示属性。

    DirectoryInfo

        4
  •  8
  •   Shubham    8 年前

    一种简单的方法是使用文件列表和目录队列。 如果使用递归程序执行相同的任务,则可能抛出OfMemory异常。 输出:添加到列表中的文件根据自上而下(宽度优先)目录树进行组织。

    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. 在循环中,将其出列,将该目录中的文件添加到列表中,然后将子文件夹添加到队列中。
        5
  •  2
  •   Community Romance    7 年前

    看见 https://stackoverflow.com/a/10728792/89584 用于处理未经授权的AccessException问题的解决方案。

        6
  •  1
  •   user25306    16 年前

    这应该能回答问题。我忽略了遍历子目录的问题,我想你已经明白了。

    希望这有帮助。

    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?
        }
    }
    
        7
  •  1
  •   Community Romance    4 年前

    这是一个与.NET 2.0兼容的全功能实现。

    List FileSystemInfo 版本

    (当心 null 价值观!)

    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); }
                }
            }
        }
    }
    
        8
  •  1
  •   Ciccio Pasticcio    4 年前

    // search file in every subdirectory ignoring access errors
        static List<string> list_files(string path)
        {
            List<string> files = new List<string>();
    
            // add the files in the current directory
            try
            {
                string[] entries = Directory.GetFiles(path);
    
                foreach (string entry in entries)
                    files.Add(System.IO.Path.Combine(path,entry));
            }
            catch 
            { 
            // an exception in directory.getfiles is not recoverable: the directory is not accessible
            }
    
            // follow the subdirectories
            try
            {
                string[] entries = Directory.GetDirectories(path);
    
                foreach (string entry in entries)
                {
                    string current_path = System.IO.Path.Combine(path, entry);
                    List<string> files_in_subdir = list_files(current_path);
    
                    foreach (string current_file in files_in_subdir)
                        files.Add(current_file);
                }
            }
            catch
            {
                // an exception in directory.getdirectories is not recoverable: the directory is not accessible
            }
    
            return files;
        }
    
    推荐文章