C # - Как быстро и оптимизировать список файлов в подкаталоге - PullRequest
1 голос
/ 29 сентября 2011

Я пытаюсь перечислить файлы во всех подкаталогах корневого каталога с помощью следующего подхода.Но это занимает много времени, когда количество файлов в миллионах.Есть ли лучший способ сделать это.

Я использую .NET 3.5, поэтому не могу использовать перечислитель: - (

        ******************* Main *************
        DirectoryInfo dir = new DirectoryInfo(path);
        DirectoryInfo[] subDir = dir.GetDirectories();
        foreach (DirectoryInfo di in subDir) //call for each sub directory
        {
             PopulateList(di.FullName, false);
        }

        *******************************************
        static void PopulateList(string directory, bool IsRoot)
        {

            System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + "dir /s/b \"" + directory + "\"");
            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo = procStartInfo;
            proc.Start();

            string fileName = directory.Substring(directory.LastIndexOf('\\') + 1);
            StreamWriter writer = new StreamWriter(fileName + ".lst");

            while (proc.StandardOutput.EndOfStream != true)
            {
                 writer.WriteLine(proc.StandardOutput.ReadLine());
                 writer.Flush();
            }
            writer.Close();
        }

Ответы [ 5 ]

2 голосов
/ 29 сентября 2011

Удалите все связанные с процессом вещи и попробуйте Directory.GetDirectories () и Directory.GetFiles () методы:

public IEnumerable<string> GetAllFiles(string rootDirectory)
{
    foreach(var directory in Directory.GetDirectories(
                                            rootDirectory, 
                                            "*", 
                                            SearchOption.AllDirectories))
    {
        foreach(var file in Directory.GetFiles(directory))
        {
            yield return file;
        }
    }
}

Из MSDN, SearchOption.AllDirectories:

Включает текущий каталог и все подкаталоги в операции поиска.Эта опция включает точки повторного анализа, такие как подключенные диски и символические ссылки в поиске.

1 голос
/ 29 сентября 2011

С миллионами файлов вы фактически сталкиваетесь с ограничением файловой системы (см. this и ищите "300 000"), так что примите это во внимание.

Что касается оптимизации, я думаювы бы действительно хотели лениво повторять, поэтому вам придется P / Invoke в FindFirstFile / FindNextFile.

1 голос
/ 29 сентября 2011

Определенно быстрее будет использовать DirectoryInfo.GetFiles в цикле для каждого каталога вместо того, чтобы создавать тонны новых процессов для чтения их вывода.

0 голосов
/ 29 сентября 2011

Предполагая, что ваши миллионы файлов распределены по нескольким подкаталогам, и вы используете .NET 4.0, вы можете посмотреть на параллельные расширения.

Использование параллельного цикла foreach для обработки списка подчиненных-каталогов, может сделать вещи намного быстрее.

Новые параллельные расширения также намного безопаснее и проще в использовании, чем попытки многопоточности на более низком уровне.

Единственное, на что нужно обратить внимание, это убедиться, что вы ограничиваетеколичество параллельных процессов к чему-то разумному.

0 голосов
/ 29 сентября 2011

Проверить уже доступны Directory.GetFiles перегрузка.Например:

var paths = Directory.GetFiles(root, "*", SearchOption.AllDirectories);

И да, это займет много времени.Но я не думаю, что вы можете увеличить его производительность, используя только классы .Net.

...