Игнорировать папки / файлы, когда каталог.GetFiles () отказано в доступе
Я пытаюсь отобразить список всех файлов, найденных в выбранном каталоге (и, возможно, любые подкаталоги). Проблема, с которой я сталкиваюсь, заключается в том, что когда метод 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 ответов:
вам придется сделать рекурсию вручную; не используйте все каталоги - посмотрите одну папку за раз, а затем попробуйте получить файлы из суб-dirs. Непроверенный, но что-то вроде ниже (Примечание использует делегат вместо построения массива):
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 } } } }
эта простая функция работает хорошо и отвечает требованиям вопросов.
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; }
также проверьте, Как выполнить итерацию по дереву каталогов.
простой способ сделать это-использовать список файлов и очередь для каталогов. Он сохраняет память. Если вы используете рекурсивную программу для выполнения той же задачи, это может вызвать исключение OutOfMemory. Вывод: файлы, добавленные в список, организованы в соответствии с деревом каталогов сверху вниз (ширина первой).
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; }действия:
- поставить корень в очередь
- в цикле, Dequeue его, добавьте файлы в этом каталоге в список, и Добавьте вложенные папки в очередь.
- повторяйте, пока очередь не опустеет.
Я знаю, что этот вопрос несколько устарел, но сегодня у меня была такая же проблема, и я нашел следующую статью, в которой подробно объясняется решение "рекурсии папок".
статья признает недостатки
GetDirectories()метод... :к сожалению, этот [С помощью метода GetDirectories ()] есть проблемы. Ключевым среди них является то, что некоторые из папки, которые вы пытаетесь прочитать, можно настроить так, чтобы текущий пользователь не может получить к ним доступ. Вместо того, чтобы игнорировать папки который у вас есть ограниченный доступ, метод бросает UnauthorizedAccessException. Однако, мы можем обойти эту проблему путем создания собственного рекурсивного кода поиска папок.
... а затем подробно представляет решение:
Это должно ответить на вопрос. Я проигнорировал вопрос о прохождении через подкаталоги, я предполагаю, что вы это выяснили.
конечно, вам не нужно иметь отдельный метод для этого, но вы можете найти его полезным местом, чтобы также проверить, что путь действителен, и иметь дело с другими исключениями, которые могут возникнуть при вызове GetFiles().
надеюсь, что это помогает.
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? } }
см.https://stackoverflow.com/a/10728792/89584 для решения, которое обрабатывает проблему UnauthorisedAccessException.
все решения выше будут пропускать файлы и / или каталоги, если какие-либо вызовы GetFiles() или GetDirectories() находятся в папках с набором разрешений.
вот полнофункциональная, .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); } } } } }
Comments