Подтвердить что ты не робот

Как читать большой (1 ГБ) txt файл в .NET?

У меня есть текстовый файл объемом 1 ГБ, который мне нужно читать по строкам. Каков наилучший и быстрый способ сделать это?

private void ReadTxtFile()
{            
    string filePath = string.Empty;
    filePath = openFileDialog1.FileName;
    if (string.IsNullOrEmpty(filePath))
    {
        using (StreamReader sr = new StreamReader(filePath))
        {
            String line;
            while ((line = sr.ReadLine()) != null)
            {
                FormatData(line);                        
            }
        }
    }
}

В FormatData() Я проверяю начальное слово строки, которое должно совпадать со словом и на основе этого приращения является целочисленной переменной.

void FormatData(string line)
{
    if (line.StartWith(word))
    {
        globalIntVariable++;
    }
}
4b9b3361

Ответ 1

Если вы используете .NET 4.0, попробуйте MemoryMappedFile, который предназначен для этого сценария.

В противном случае вы можете использовать StreamReader.ReadLine.

Ответ 2

Использование StreamReader, вероятно, является способом, поскольку вы не хотите, чтобы весь файл в памяти сразу. MemoryMappedFile больше для случайного доступа, чем последовательное чтение (он в десять раз быстрее для последовательного чтения и сопоставления памяти в десять раз быстрее для произвольного доступа).

Вы также можете попытаться создать свой потоковый движок из файлового потока с помощью FileOptions, установленного в SequentialScan (см. FileOptions Enumeration), но я сомневаюсь, что он сделает много разницы.

Однако есть способы сделать ваш пример более эффективным, так как вы форматируете в том же цикле, что и чтение. Вы теряете часы, поэтому, если вам нужна еще большая производительность, было бы лучше с многопотоковым асинхронным решением, где один поток считывает данные, а другой форматирует его по мере его появления. Checkout BlockingColletion, который может соответствовать вашим потребностям:

Блокировка коллекции и проблема производителя и потребителя

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

Ответ 3

Вы можете использовать LINQ:

int result = File.ReadLines(filePath).Count(line => line.StartsWith(word));

File.ReadLines возвращает IEnumerable <String> , который лениво читает каждую строку из файла без загрузки весь файл в память.

Enumerable.Count подсчитывает строки, начинающиеся со слова.

Если вы вызываете это из потока пользовательского интерфейса, используйте BackgroundWorker.

Ответ 5

StreamReader.ReadLine должен работать нормально. Пусть структура выбирает буферизацию, если вы не знаете, используя профилирование, вы можете сделать лучше.

Ответ 7

Я бы прочитал файл по 10 000 байт за раз. Затем я проанализировал эти 10 000 байт и разделил их на строки и передал их в функцию FormatData.

Бонусные точки для разделения чтения и анализа строк на несколько потоков.

Я бы определенно использовал StringBuilder, чтобы собрать все строки и создать строковый буфер, чтобы хранить около 100 строк в памяти всех время.

Ответ 8

Я столкнулся с такой же проблемой на нашем производственном сервере Agenty, где мы видим большие файлы (иногда 10-25 gb (\ t ) с разделителями txt с разделителями). И после многих испытаний и исследований я нашел лучший способ читать большие файлы в небольших фрагментах с помощью цикла for/foreach и устанавливать смещение и ограничивать логику с помощью File.ReadLines().

int TotalRows = File.ReadLines(Path).Count(); // Count the number of rows in file with lazy load
int Limit = 100000; // 100000 rows per batch
for (int Offset = 0; Offset < TotalRows; Offset += Limit)
{
  var table = Path.FileToTable(heading: true, delimiter: '\t', offset : Offset, limit: Limit);

 // Do all your processing here and with limit and offset and save to drive in append mode
 // The append mode will write the output in same file for each processed batch.

  table.TableToFile(@"C:\output.txt");
}

Смотрите полный код в моей библиотеке Github: https://github.com/Agenty/FileReader/

Полное раскрытие информации - я работаю для Agenty, компании, которая владела этой библиотекой и веб-сайтом.