Каталог C #, перечисляющий массивный каталог - PullRequest
4 голосов
/ 21 декабря 2009

Вот сценарий:

У меня есть каталог с 2+ миллионами файлов. Приведенный ниже код записывает все файлы примерно за 90 минут. У кого-нибудь есть способ ускорить его или сделать этот код более эффективным? Я также хотел бы записать только имена файлов в списке.

string lines = (listBox1.Items.ToString());
string sourcefolder1 = textBox1.Text;  
string destinationfolder = (@"C:\anfiles");  
using (StreamWriter output = new StreamWriter(destinationfolder + "\\" + "MasterANN.txt"))  
{  
    string[] files = Directory.GetFiles(textBox1.Text, "*.txt");  
    foreach (string file in files)  
    {  
        FileInfo file_info = new FileInfo(file);
        output.WriteLine(file_info.Name);  
    }  
 }  

Замедление состоит в том, что он пишет по 1 строке за раз.

Требуется около 13-15 минут, чтобы получить все необходимые файлы для записи.

Следующие 75 минут создают файл.

Ответы [ 5 ]

8 голосов
/ 21 декабря 2009

Может помочь, если вы не создадите экземпляр FileInfo для каждого файла, вместо этого используйте Path.GetFileName:

string lines = (listBox1.Items.ToString());  
        string sourcefolder1 = textBox1.Text;  
        string destinationfolder = (@"C:\anfiles");  
        using (StreamWriter output = new StreamWriter(Path.Combine(destinationfolder, "MasterANN.txt"))  
        {  
            string[] files = Directory.GetFiles(textBox1.Text, "*.txt");  
            foreach (string file in files)  
            {  
                output.WriteLine(Path.GetFileName(file));
            }  
        }
6 голосов
/ 21 декабря 2009

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

5 голосов
/ 21 декабря 2009

Первое, что мне нужно знать, это где замедление? для выполнения Directory.GetFiles () требуется 89 минут или задержка распределяется по вызовам на FileInfo file_info = new FileInfo(file);?

Если задержка связана с последним, вы, вероятно, можете ускорить процесс, получив имя файла по пути вместо создания экземпляра FileInfo для получения имени файла.

System.IO.Path.GetFileName(file);
3 голосов
/ 21 декабря 2009

По моему опыту, Directory.GetFiles замедляет вас (кроме вывода на консоль). Чтобы преодолеть это, P / Invoke в FindFirstFile / FindNextFile , чтобы избежать всего потребления памяти и общего отставания.

1 голос
/ 20 января 2014

Использование Directory.EnumerateFiles не нужно сначала загружать все имена файлов в память. Проверьте это: Справка по C # directory.getfiles

В вашем случае код может быть:

using (StreamWriter output = new StreamWriter(destinationfolder + "\\" + "MasterANN.txt"))
{
    foreach (var file in Directory.EnumerateFiles(sourcefolder, "*.txt"))
    {
        output.WriteLine(Path.GetFileName(file));
    }
}

Из этого документа сказано, что:

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

Так что, если у вас достаточно памяти, Directory.GetFiles в порядке. Но Directory.EnumerateFiles намного лучше, когда папка содержит миллионы файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...