Извлечение файлов из каталога, который содержит большое количество файлов - PullRequest
60 голосов
/ 23 октября 2011

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

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

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

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

Ответы [ 6 ]

87 голосов
/ 23 октября 2011

Вы пробовали метод EnumerateFiles класса DirectoryInfo?

Как говорит MSDN

Методы EnumerateFiles и GetFiles отличаются следующим образом: используйте EnumerateFiles, вы можете начать перечисление коллекции FileInfo объекты до возвращения всей коллекции; когда ты используйте GetFiles, вы должны ждать, пока весь массив FileInfo объектов быть возвращен, прежде чем вы сможете получить доступ к массиву. Поэтому, когда вы работая со многими файлами и каталогами, EnumerateFiles может быть больше эффективный.

44 голосов
/ 23 октября 2011

В .NET 4.0 Directory.EnumerateFiles(...) равен IEnumerable<string> (вместо string[] из Directory.GetFiles(...)), поэтому он может передавать записи в потоковом режиме, а не буферизовать их все; т.е.

foreach(var file in Directory.EnumerateFiles(path)) {
    // ...
}
17 голосов
/ 23 октября 2011

вы попали в ограничение самой файловой системы Windows.Когда количество файлов в каталоге становится большим (а 14M выходит за рамки этого порога), доступ к каталогу становится невероятно медленным.На самом деле не имеет значения, читаете ли вы один файл за раз или 1000, это просто доступ к каталогу.

Один из способов решить эту проблему - создать подкаталоги и разбить ваши файлы на группы.Если в каждом каталоге 1000-5000 (догадываясь, но вы можете поэкспериментировать с реальными числами), то вы должны получить приличную производительность при открытии / создании / удалении файлов.

Вот почему, если вы посмотрите на приложения, такие как Doxygen, который создаетфайл для каждого класса, они следуют этой схеме и помещают все в 2 уровня подкаталогов, которые используют случайные имена.

6 голосов
/ 23 октября 2011

Используйте Win32 Api FindFile функции, чтобы сделать это без блокировки приложения.

Вы также можете вызвать Directory.GetFiles в System.Threading.Task (TPL), чтобы ваш пользовательский интерфейс не зависал.

5 голосов
/ 16 декабря 2014

Наслаждайтесь.

    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();
    }
3 голосов
/ 16 апреля 2014

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

...