Exclude last line from StreamReader in C#

1.8k views Asked by At

I'm saving some DataGridView's data into a text file(for data I'm refering to the content of each cell), and at the last line of the TXT File, I am storing the number of rows of the dataGridView with a "-" at the start of the line.

Now, I can read my data perfectly into my DVG, but how can I exclude the last line which contains my row count and also use it to read its stored int?

The code I use for reading the data into the DVG:

void LoadDVGData()
    {
        StreamReader sr = new StreamReader(open.FileName);
        foreach (DataGridViewRow row in editDGV.Rows)
        {
            foreach (DataGridViewCell cell in row.Cells)
            {
                string content = sr.ReadLine();
                cell.Value = content;
            }
        }
        sr.Close();
    }

Thanks in Advance. - CCB

2

There are 2 answers

6
xxbbcc On

I assume sr is the StreamReader that reads your text file - you should wrap that in a using or try..finally block to ensure correct cleanup in case of errors.

Your current setup doesn't work very well for cases where the text file doesn't match the number of rows / cells that you have in the DataGridView (DGV): you try reading a value from the file for each cell and if the wrong file is specified, you may attempt to read beyond the end of the file. You should have more error handling around this code because there may be various problem spots during reading the file: too few rows, too few cells for a row, invalid value for a particular cell, etc.

Your setup doesn't lend itself very well to handling. If you control the format of the text file, I'd recommend to change the format so that the very first row is the count and then each row in the text file describes a complete row for the DGV, using TAB as the delimiter. It'd be far simpler to load such a file. (You can even have the row count and column count on the first row to give you even more information about the data; you can never have too much metadata about input data.)

So your new textfile format would look something like:

3{TAB}5
R1C1{TAB}R1C2{TAB}R1C3{TAB}R1C4{TAB}R1C5{CRLF}
R2C1{TAB}R2C2{TAB}R2C3{TAB}R2C4{TAB}R2C5{CRLF}
R3C1{TAB}R3C2{TAB}R3C3{TAB}R3C4{TAB}R3C5{CRLF}

If you cannot change the text file format, then just read the file twice - first seek to the end of the file and read back to the end of the line before the last - then just read one line from it - it should be the row count. You can do this by looking for a newline in the file going from the end. Then just seek to the beginning of the file and read so many lines from it.

Edit:

As @vesan commented under the question, if your input file is not huge, you can just call File.ReadAllLines() to get all lines in a string[]. It's trivial to process it then. Using a more convenient file format would work, though, for any file size. Reading all lines assumes that the input file is not huge.

Edit 2:

For example (error handling omitted for brevity):

var sLines = File.ReadAllLines ( open.FileName );
var nRowCount = int.Parse ( sLines[sLines.Length - 1] );
var nIndex = 0;

foreach (DataGridViewRow row in editDGV.Rows)
{
    foreach (DataGridViewCell cell in row.Cells)
    {
        cell.Value = sLines[nIndex];
        nIndex++;
    }
}

If your text file is correct, nRowCount will have the correct number of rows and you'll never actually read the last element of your array into the DGV.

0
Nicholas Carey On

You just need to maintain one token of look ahead so that you can answer the question, "Is this the last line?" (if you have a current line, but no next line, you're positioned at the last line.

Here's one approach, which is probably about as simple as it gets:

void LoadDVGData()
{
  using ( StreamReader sr = new StreamReader(open.FileName) )
  {
    string currentLine = sr.ReadLine() ;
    string nextLine    = sr.ReadLine() ;

    foreach (DataGridViewRow row in editDGV.Rows)
    {
      foreach (DataGridViewCell cell in row.Cells)
      {
        if ( currentLine == null ) throw new InvalidOperationException("Hmph. We seem to have run out of input data");

        cell.Value = currentLine ;

        currentLine = nextLine ;
        nextLine = sr.ReadLine() ;

      } //end cols loop
    } // end rows loop

  } // end using block

  return;
}