Извлечение файлов из каталога, содержащего большое количество файлов


У меня есть каталог, который содержит почти 14,000,000 аудио сэмплов в *.формат WAV.

все простое хранилище, без подкаталогов.

Я хочу перебирать файлы, но когда я использую DirectoryInfo.GetFiles() в этой папке все приложение зависает на минуты!

можно ли это сделать по-другому? Может быть, прочитать 1000, обработать их, а затем взять следующую 1000 и так далее?

6 58

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();
    }

Я много раз сталкивался с этой проблемой доступа к большим файлам в одном каталоге. Подкаталоги являются хорошим вариантом, но вскоре даже они не предлагают большую помощь иногда. Теперь я создаю индексный файл-текстовый файл с именами всех файлов в каталоге (при условии, что я создаю файлы в этом каталоге). Затем я читаю индексный файл, а затем открываю фактический файл из каталога для обработки