Извлечение файлов из каталога, содержащего большое количество файлов
У меня есть каталог, который содержит почти 14,000,000 аудио сэмплов в *.формат WAV.
все простое хранилище, без подкаталогов.
Я хочу перебирать файлы, но когда я использую DirectoryInfo.GetFiles()
в этой папке все приложение зависает на минуты!
можно ли это сделать по-другому? Может быть, прочитать 1000, обработать их, а затем взять следующую 1000 и так далее?
6 ответов:
вы пробовали EnumerateFiles метод класса DirectoryInfo?
как говорит MSDN
The
EnumerateFiles
иGetFiles
методы различаются следующим образом: когда вы используйтеEnumerateFiles
, вы можете начать перечисление сбораFileInfo
объекты перед возвратом всей коллекции; когда вы используйтеGetFiles
, вы должны ждать, пока весь массивFileInfo
объекты будет возвращен до того, как вы сможете получить доступ к массиву. Поэтому, когда вы рабочий со многими файлами и каталогами,EnumerateFiles
может быть больше эффективный.
в .NET 4.0,
Directory.EnumerateFiles(...)
иIEnumerable<string>
(вместоstring[]
наDirectory.GetFiles(...)
), поэтому он может передавать записи, а не буферизировать их все; т. е.foreach(var file in Directory.EnumerateFiles(path)) { // ... }
вы попали в ограничение самой файловой системы Windows. Когда количество файлов в каталоге растет до большого числа (и 14M-это путь за этот порог), доступ к каталогу становится невероятно медленным. Это действительно не имеет значения, если Вы читаете один файл за раз или 1000, это просто открыть каталог.
один из способов решить эту проблему-создать подкаталоги и разбить файлы на группы. Если каждый каталог имеет 1000-5000 (предполагаю, но вы можете экспериментировать с фактические цифры), то вы должны получить достойную производительность открытия/создания/удаления файлов.
вот почему, если вы посмотрите на приложения, такие как Doxygen, который создает файл для каждого класса, они следуют этой схеме и помещают все в 2 уровня подкаталогов, которые используют случайные имена.
Использовать Win32 Api FindFile функции, чтобы сделать это без блокировки приложения.
вы также можете вызвать каталог.Заражен в
наслаждайтесь.
public List<string> LoadPathToAllFiles(string pathToFolder, int numberOfFilesToReturn) { var DirInfo = new DirectoryInfo(pathToFolder); var firstFiles = DirInfo.EnumerateFiles().Take(numberOfFilesToReturn).ToList(); return firstFiles.Select(l => l.FullName).ToList(); }
Я много раз сталкивался с этой проблемой доступа к большим файлам в одном каталоге. Подкаталоги являются хорошим вариантом, но вскоре даже они не предлагают большую помощь иногда. Теперь я создаю индексный файл-текстовый файл с именами всех файлов в каталоге (при условии, что я создаю файлы в этом каталоге). Затем я читаю индексный файл, а затем открываю фактический файл из каталога для обработки