7

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?

MatanKri
  • 263
  • 1
  • 3
  • 13
  • You tried right controls, but in wrong mode. Search "winforms **virtual mode** " (to example, listbox). – Sinatr May 06 '14 at 15:15

2 Answers2

10

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!

drew_w
  • 10,320
  • 4
  • 28
  • 49
  • Why are you not using virtualization, like @Black From is suggesting (and is available also on WPF) – Yishai Galatzer May 06 '14 at 15:31
  • 1
    @YishaiGalatzer "virtualization" as you call it would work with a ListView *IF* you know the exact number of items ahead of time. It also only restricts to a specific interface option rather than allowing the data to be displayed in whatever manner is desired. Based on both of these facts I deemed those to be not as good of a solution as a generic file reader which can be modified to do whatever the OP wants! – drew_w May 06 '14 at 15:33
  • @YishaiGalatzer Added a note to the answer to explain the pros/cons of virtual mode : ) – drew_w May 06 '14 at 15:41
  • Because writing your own virtualization is NEVER as straightforward as you suggest above. Depending on the required quality of the end product he might be spending days tweaking and tweaking it to get it right. For example scrolling to the end or top are common scenarios where things may go wrong. So nothing wrong with your idea, it's not a solution for a newbie. Note that the WPF controls do not have the limitation you put in your answer. (And thanks!) – Yishai Galatzer May 06 '14 at 15:42
  • @YishaiGalatzer Noted. Unfortunately the OP is using winforms. – drew_w May 06 '14 at 15:43
1

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.

Black Frog
  • 11,595
  • 1
  • 35
  • 66