Страницы

Поиск по вопросам

пятница, 12 апреля 2019 г.

DirectoryInfo.EnumerateFiles => Исключение

Нужно получить все файлы по заданной маске. Метод EnumerateFiles выдает исключение, если какой-то файл имеет системные права доступа. Как это обойти?
var sourceDir = new DirectoryInfo(path); foreach (var f in sourceDir.EnumerateFiles("*.txt", SearchOption.AllDirectories)) { var lvItem = new ListViewItem(Path.GetFileName(f.FullName), 0); lvItem.SubItems.Add(Path.GetDirectoryName(f.FullName)); var fileInfo = new FileInfo(f.FullName); lvItem.SubItems.Add(fileInfo.Length + " байт"); lvItem.SubItems.Add(Directory.GetLastWriteTime(f.FullName).ToShortDateString()); uiContext.Send(d => listView1.Items.Add(lvItem), null); }


Ответ

Судя по всему, ничего лучше ручной рекурсии с отловом исключений нет.
Можно попробовать так:
static IEnumerable EnumerateFilesDeepIgnoringAccessException( DirectoryInfo root, string mask) { var localResult = new List(); try { localResult = root.EnumerateFiles(mask).ToList(); } catch (UnauthorizedAccessException) { // ignore it yield break; }
foreach (var fi in localResult) yield return fi;
foreach (var di in root.EnumerateDirectories()) { foreach (var fi in EnumerateFilesDeepIgnoringAccessException(di, mask)) yield return fi; } }
Код основан на официальном примере, модифицирован для ленивого обхода.

Можно ещё избавиться от рекурсии стандартным путём — добавить явную очередь каталогов для обхода. Однако не думаю, что это даст существенный выигрыш по скорости по сравнению с обходом файловой системы.

Специфически для вашего кода, я не стал бы заниматься обходом файловой системы в том же потоке, в котором бежит UI — иначе зависаний не избежать. Вам стоит подумать об обходе в отдельном потоке.

Комментариев нет:

Отправить комментарий