2016-04-22 3 views
1

Я хочу прочитать в файле, который в этом случае равен 3 Мб . Это занимает около 50-60 секунд, что кажется очень медленным. Кто-нибудь знает, как сделать это быстрее?StreamReader очень медленный для больших файлов

string text = null; 
using (StreamReader sr = new StreamReader(file, Encoding.Default)) 
{ 
    string line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     text += (line); 
     backgroundWorker1.ReportProgress(text.Length); 
    } 
} 

Мне также нужно использовать фоновый рабочий, так что я могу сообщить процент, который был загружен (для файлов вокруг 500mb для 1gb)

+2

Вы пробовали свой тест без конкатенации в 'System.String', то есть комментируете строку' text + = (line); '? –

+0

Возможно, вы не хотите читать его в строке, но с фиксированной длиной буфера. – rinukkusu

+0

@ Christian.K Я сделал это, и это было мгновенно. Теперь, как я могу получить текст? – jLynx

ответ

5

Используйте StringBuilder, чтобы создать свою линию - это гораздо более производительным, чем конкатенация строк.

using System.Text; 

//... 

StringBuilder text = new StringBuilder(); 
using (StreamReader sr = new StreamReader(file, Encoding.Default)) 
{ 
    string line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     text.Append(line); 
     backgroundWorker1.ReportProgress(text.Length); 
    } 
} 

// ... 
// Do something with the file you have read in. 
Console.WriteLine(text.ToString()); 
+0

Это вызовет исключение NullReferenceException; похоже, что 'text' никогда не инициализируется? –

+0

Но 'text' _is_ инициализирован ... на' null' (третья непустая строка фрагмента). – Nuffin

+0

Извините - ошибка копирования-вставки. Исправлено. –

0

Вы можете использовать эту строку:

string text = System.IO.File.ReadAllText(file); 
+0

Да, но тогда нет способа сообщить о прогрессе, делая это (похоже, что это важно для ОП - тогда, возможно, нет). –

+1

Кроме того, если он имеет дело с большими файлами, он может не захотеть сразу их прочитать в памяти (он упоминает 1GB-файл в своем вопросе). –

4

StreamReader очень медленно для больших файлов C#

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

текст + = (линия);

Эта строка создает новую строку. Для этого необходимо выделить новую память. Для большого файла это ЗНАЧИТЕЛЬНОЕ количество созданного мусора. И чем дольше это получается, тем больше операций копирования вы делаете.

Если это то, что вы используете его для

backgroundWorker1.ReportProgress (text.Length);

также бесполезно. Вы также можете иметь

Int textLength = 0

, что вы установите

textLength + = line.Length

без всяких манипуляций с текстом.

Вы ДОЛЖНЫ знать это. Проблемы с производительностью? НИКОГДА не предполагайте, ВСЕГДА мы профайлер, который очень быстро показал вам эту проблему. Это базовая отладка.

Некоторый фон математика, кстати:

(для файлов вокруг 500mb до 1Гба)

Это означает, что после загрузки 500MB данных вашего кода делают 500МБЫ (если файл был unicode) до 1gb (строка, удваивающая размер файла ascii) операция копирования PER LINE.

Возможно, вам захочется посмотреть скорость памяти вашего компьютера. В зависимости от сервера и т.д.вы можете ограничить до 50 гб в секунду (high end X99 - более новые DDR 4-памяти быстрее, но на рабочих станциях в общем случае гораздо меньше каналов, поэтому они медленнее), а копия считается двойной (чтение и запись). Это означает, что вы действительно начинаете работать с сценариями «копирование строки - это перегрузка их шины памяти».

Смежные вопросы