Я пишу программу, которая должна искать каталог и все его подкаталоги для файлов с определенным расширением. Это будет использоваться как на локальном, так и на сетевом диске, поэтому производительность является проблемой.Существует ли более быстрый способ найти все файлы в каталоге и во всех подкаталогах?
Вот рекурсивный метод я использую сейчас:
private void GetFileList(string fileSearchPattern, string rootFolderPath, List<FileInfo> files)
{
DirectoryInfo di = new DirectoryInfo(rootFolderPath);
FileInfo[] fiArr = di.GetFiles(fileSearchPattern, SearchOption.TopDirectoryOnly);
files.AddRange(fiArr);
DirectoryInfo[] diArr = di.GetDirectories();
foreach (DirectoryInfo info in diArr)
{
GetFileList(fileSearchPattern, info.FullName, files);
}
}
я мог установить SearchOption в AllDirectories и не использовать рекурсивный метод, но в будущем я хочу, чтобы вставить код, чтобы уведомить пользователь, какая папка в настоящее время проверяется.
Пока я создаю список объектов FileInfo, теперь все, что мне действительно волнует, это пути к файлам. У меня будет существующий список файлов, который я хочу сравнить с новым списком файлов, чтобы увидеть, какие файлы были добавлены или удалены. Есть ли более быстрый способ создания этого списка путей к файлу? Есть ли что-нибудь, что я могу сделать, чтобы оптимизировать этот поиск файлов вокруг запросов к файлам на общем сетевом диске?
Update 1
Я попытался создать нерекурсивный метод, который делает то же самое, первым найти все подкаталоги, а затем итеративно сканированием каждого каталога файлов. Вот метод:
public static List<FileInfo> GetFileList(string fileSearchPattern, string rootFolderPath)
{
DirectoryInfo rootDir = new DirectoryInfo(rootFolderPath);
List<DirectoryInfo> dirList = new List<DirectoryInfo>(rootDir.GetDirectories("*", SearchOption.AllDirectories));
dirList.Add(rootDir);
List<FileInfo> fileList = new List<FileInfo>();
foreach (DirectoryInfo dir in dirList)
{
fileList.AddRange(dir.GetFiles(fileSearchPattern, SearchOption.TopDirectoryOnly));
}
return fileList;
}
Update 2
Хорошо, так что я несколько тестов на локальном и удаленном папку оба из которых имеют много файлов (~ 1200). Вот методы, на которых я запускал тесты. Результаты приведены ниже.
- GetFileListA(): Non-рекурсивное решение в вышеприведенном обновлении. Я думаю, что это эквивалентно решению Джея.
- GetFileListB(): Рекурсивный метод от первоначального вопроса
- GetFileListC(): Получает все директории со статическим Directory.GetDirectories() методом. Затем получает все пути к файлу со статическим методом Directory.GetFiles(). Заполняет и возвращает список
- GetFileListD(): Решение Марка Гравелла с использованием очереди и возвращает IEnumberable. Я заполнил список с полученным IEnumerable
- DirectoryInfo.GetFiles: Никакой дополнительный метод не создан. Создал экземпляр DirectoryInfo из корневого каталога. Названный GetFiles с использованием SearchOption.AllDirectories
- Directory.GetFiles: Нет дополнительный метод создан. Вызывается статическим методом GetFiles каталога с использованием SearchOption.AllDirectories
Method Local Folder Remote Folder GetFileListA() 00:00.0781235 05:22.9000502 GetFileListB() 00:00.0624988 03:43.5425829 GetFileListC() 00:00.0624988 05:19.7282361 GetFileListD() 00:00.0468741 03:38.1208120 DirectoryInfo.GetFiles 00:00.0468741 03:45.4644210 Directory.GetFiles 00:00.0312494 03:48.0737459
. , .so похоже, что Марк самый быстрый.
выглядит довольно хорошо для меня, мне будет интересно узнать, есть ли другой способ сделать это. –
Мне интересно, если создание объекта FileInfo фактически проводит какое-либо время, читая что-либо из файла, или если он просто знает путь к файлу, который он представляет, и запрашивает только фактический файл, если я запрашиваю некоторую другую информацию из одного из своих свойств как размер или измененная дата. –
Быстрый тест, AllDirectories быстрее, но не сильно. @Eric, я думаю, что он только читает метаданные файла, так что я могу ошибаться в этом. –