Самый быстрый способ нарисовать большой текстовый файл в C# winforms

У меня есть большой текстовый файл (~100 МБ), я храню его строки в списке строк. моя Winform иногда требует показать часть этого, например, 500 000 строк.

Я пытался использовать ListBox, RichTextBox и TextBox, но рисование занимает слишком много времени.

Например, TextBox отображает 500 000 строк за 25 секунд, а блокнот немедленно открывает текстовый файл такого размера.

что будет самым быстрым решением для этой цели?

2 ответа

Почему бы не открыть поток файлов и просто прочитать первые несколько строк. Ты можешь использовать seek как пользователь прокручивает файл и отображает соответствующие строки. Дело в том, что чтение всего файла в память занимает много времени, поэтому не делайте этого!

Стартовый код

Ниже приведен фрагмент кода, который не завершен, но по крайней мере должен помочь вам начать:

// estimate the average line length in bytes somehow:
int averageLineLengthBytes = 100;

// also need to store the current scroll location in "lines"
int currentScroll = 0;

using (var binaryReader = new StreamReader(new FileStream(fileName, FileAccess.Read)))
{
    if (binaryReader.BaseStream.CanSeek)
    {
        // seek the location to read:
        binaryReader.BaseStream.Seek(averageLineLengthBytes * currentScroll, SeekOrigin.Begin);

        // read the next few lines using this command
        binaryReader.ReadLine();
    }
    else
    {
        // revert to a slower implementation here!
    }
}

Самым большим трюком будет оценка того, какой длины должна быть полоса прокрутки (сколько строк в файле). Для этого вам придется либо изменить полосу прокрутки по мере прокрутки пользователем, либо вы можете использовать предварительные знания о том, как долго типичные строки находятся в этом файле, и оценить длину на основе общего количества байтов. В любом случае, надеюсь, это поможет!

Примечание о виртуальном режиме

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

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

Если вы не можете соответствовать этим критериям, то виртуальный режим не будет особенно полезным. Ответ, который я представил seek будет работать независимо от того, можете ли вы выполнить эти действия. Конечно, если вы можете соответствовать этим минимальным критериям, тогда непременно ищите виртуальный режим для просмотра списка, и вы должны найти действительно полезную информацию!

У ListView есть свойство Virtual Mode. Это позволяет вам загружать только те данные, которые вы видите, используя Retrieve Virtual Item Event. Поэтому, когда это событие инициируется, например, для элемента с номером 40000, вы выполняете поиск по файлу, считанному в строке.

Вы также можете найти пример виртуального списка в Microsoft. Это действительно старый, но он дает вам основную идею.

Другие вопросы по тегам