3

I am writing a fairly simple windows form C# application in Visual Studio 2015. Here is one of my handlers:

private void button2_Click(object sender, EventArgs e)
{
    listBoxCodes.Items.Clear();
    listBoxDuplicates.Items.Clear();

    Cursor.Current = Cursors.WaitCursor;
    Application.DoEvents();

    progressBar.Value = 0;
    using (var reader = new StreamReader(textBoxGENIO.Text))
    {
        // progressBar is set for 5 unit intervals (from 0 to 100)

        // How can I show % complete reading the file?

        string line;
        while ((line = reader.ReadLine()) != null)
        {
            if(line.Length > 8 && line.Substring(0, 4) == "080,")
            {
                string strCode = line.Substring(4, 4);

                if (listBoxCodes.FindStringExact(strCode) == -1)
                    listBoxCodes.Items.Add(strCode);
                else
                    listBoxDuplicates.Items.Add(strCode);
            }
        }
    }

    Cursor.Current = Cursors.Default;
}

Now, I understand that I can read the file through once, to get the total number of lines, and then read the file through again, and do progress monitoring based on the percentage through the line count.

But I want to avoid reading the file twice because they can get very large.

Is there any way that I can use the file position / file size instead to establish the percentage complete?

I can't see any Position method in the StreamReader object.

Thank you.

Update: Currently looking at this question which may be the answer:

Tracking the position of the line of a streamreader

Update:

My calculations seem to be wrong:

private void button2_Click(object sender, EventArgs e)
{
    listBoxCodes.Items.Clear();
    listBoxDuplicates.Items.Clear();

    Cursor.Current = Cursors.WaitCursor;
    Application.DoEvents();

    int iLastPercentage = -1;

    progressBar.Value = 0;
    using (var reader = new StreamReader(textBoxGENIO.Text))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            // progressBar is set for 5 unit intervals (from 0 to 100)

            // How can I show % complete reading the file?
            int iPercentage = Convert.ToInt32(((double)reader.BaseStream.Length / 100.0) * (double)reader.BaseStream.Position);
            if (iLastPercentage == -1 || (iPercentage - iLastPercentage >= 5))
            {
                progressBar.PerformStep();
                iLastPercentage = iPercentage;
                Application.DoEvents();
            }

            if (line.Length > 8 && line.Substring(0, 4) == "080,")
            {
                string strCode = line.Substring(4, 4);

                if (listBoxCodes.FindStringExact(strCode) == -1)
                    listBoxCodes.Items.Add(strCode);
                else
                    listBoxDuplicates.Items.Add(strCode);
            }
        }
    }

    Cursor.Current = Cursors.Default;
}

}

Community
  • 1
  • 1
Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164

2 Answers2

4

See if below works for you:

private void button2_Click(object sender, EventArgs e)
{
    listBoxCodes.Items.Clear();
    listBoxDuplicates.Items.Clear();

    Cursor.Current = Cursors.WaitCursor;
    Application.DoEvents();

    progressBar.Value = 0;
    using (var reader = new StreamReader(textBoxGENIO.Text))
    {
        // progressBar is set for 5 unit intervals (from 0 to 100)

        // How can I show % complete reading the file?
        Stream baseStream = reader.BaseStream;
        long length = baseStream.Length;

        string line;
        while ((line = reader.ReadLine()) != null)
        {
            if(line.Length > 8 && line.Substring(0, 4) == "080,")
            {
                string strCode = line.Substring(4, 4);

                if (listBoxCodes.FindStringExact(strCode) == -1)
                    listBoxCodes.Items.Add(strCode);
                else
                    listBoxDuplicates.Items.Add(strCode);
            }

            progressBar.Value = baseStream.Position / length * 100;
            // Add code to update your progress bar UI
        }
    }

    Cursor.Current = Cursors.Default;
}
Mango Wong
  • 629
  • 6
  • 16
  • Thanks. I had to convert the percentage value. I tried: `progressBar.Value = Convert.ToInt32(baseStream.Position / length * 100); Application.DoEvents();` but for some reason it does all the progress bar updates **after** the loop finishes. So I am no better off. :( – Andrew Truckle May 20 '16 at 11:07
  • How about calling `Control.Refresh()` on your progress bar control? – Mango Wong May 20 '16 at 11:11
  • Seems too slow down if I do that. It looks like I have to read the file in a worker thread and communicate with the GUI to update the progress and populate the list boxes. – Andrew Truckle May 20 '16 at 11:15
  • 1
    If so, you may reduce number of calling `Control.Refresh()`, maybe call once only for every 5%. Of course, separate the code in another working thread would be a better approach. – Mango Wong May 20 '16 at 11:18
4

This is the correct way, you must typecast it to double

private void button_Load_Int_Click(object sender, EventArgs e)
    {
        Application.DoEvents();
        progressBar.Value = 0;
        using (StreamReader sr = new StreamReader(pathInt))
        {
            Stream baseStream = sr.BaseStream;
            long length = baseStream.Length;
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                string strCode = line.Substring(4, 4);

                if (listBoxCodes.FindStringExact(strCode) == -1)
                    listBoxCodes.Items.Add(strCode);
                else
                    listBoxDuplicates.Items.Add(strCode)
                progressBar.Value = Convert.ToInt32((double)baseStream.Position / length * 100);
                Application.DoEvents();
            }
        }
    }
Pan Markosian
  • 101
  • 14