Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to draw a large text file in C# winforms

I have a large text file (~100MB) that I keep it's lines in a list of strings. my Winform requires occasionally to show a part of it, for example 500,000 lines.

I have tried using a ListBox, RichTextBox and TextBox, but the drawing takes too much time.

for example, TextBox takes 25 seconds to show 500,000 lines, whereas notepad opens a text file of this size immediately.

what will be the fastest solution for this purpose?

like image 670
MatanKri Avatar asked May 06 '14 15:05

MatanKri


People also ask

How can I open a text file larger than 1gb?

Solution 1: Download a Dedicated Large File Viewer There are even online tools that will let you upload a large text file to a web application that will open them online, such as http://www.readfileonline.com. On Windows, there is a program that comes pre-installed and can open text files of any size.

How fast is fread?

The results speak for themselves. Not only was fread() almost 2.5 times faster than readr's functionality in reading and binding the data, but perhaps even more importantly, the maximum used memory was only 15.25 GB, compared to readr's 27 GB.


2 Answers

Why not open a file stream and just read the first few lines. You can use seek as the user scrolls in the file and display the appropriate lines. The point is - reading the whole file into memory takes to long so don't do that!

Starter Code

The following is a short code snippet that isn't complete but it should at least get you started:

// 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!
    }
}

The biggest trick is going to be estimating how long the scroll bar needs to be (how many lines are in the file). For that you are going to have to either alter the scroll bar as the user scrolls or you can use prior knowledge of how long typical lines are in this file and estimate the length based on the total number of bytes. Either way, hope this helps!

A Note About Virtual Mode

Virtual mode is a method of using a ListBox or similar list control to load the items on an as needed basis. The control will execute a callback to retrieve the items based on an index when the user scrolls within the control. This is a viable solution only if your data meets the following criteria:

  • You must know (up front) the number of data items that you wish to present. If you need to read the entire file to get this total, it isn't going to work for you!
  • You must be able to retrieve a specific data item based an index for that item without reading the entire file.
  • You must be willing to present the data in an icon, small details, details or other supported format (or be willing to go to a ton of extra work to write a custom list view).

If you cannot meet these criteria, then virtual mode is not going to be particularly helpful. The answer I presented with seek will work regardless of whether or not you can perform these actions. Of course, if you can meet these minimum criteria, then by all means - look up virtual mode for list views and you should find some really useful information!

like image 173
drew_w Avatar answered Oct 18 '22 00:10

drew_w


ListView have a Virtual Mode property. It allows you to only load the data are in view using the Retrieve Virtual Item Event. So when that event is trigger for item number 40,000 for example, you would perform a seek on the file read in the line.

You can also find example of a virtual list box on Microsoft. It really old, but it gives you a basic idea.

like image 30
Black Frog Avatar answered Oct 18 '22 01:10

Black Frog