3

So I'm doing a project where I am reading in a config file. The config file is just a list of string like "D 1 1", "C 2 2", etc. Now I haven't ever done a read/write in C# so I looked it up online expecting to find some sort of rendition of C/C++ .eof(). I couldn't find one.

So what I have is...

TextReader tr = new StreamReader("/mypath");

Of all the examples online of how I found to read to the end of a file the two examples that kept occurring were

while ((line = tr.ReadLine() != null)

or

while (tr.Peek() >= 0)

I noticed that StreamReader has a bool EndOfStream but no one was suggesting it which led me to believe something was wrong with that solution. I ended up trying it like this...

while (!(tr as StreamReader).EndOfStream)

and it seems to work just fine.

So I guess my question is would I experience issues with casting a TextReader as a StreamReader and checking EndOfStream?

MattMacdonald
  • 93
  • 1
  • 1
  • 9
  • 2
    It's fine. The cast is nails on a black board however. Using *as* is very wrong here. That can only produce a lousy NullReference exception instead of a good InvalidCast. – Hans Passant Nov 08 '11 at 08:48

6 Answers6

5

One obvious downside is that it makes your code StreamReader specific. Given that you can easily write the code using just TextReader, why not do so? That way if you need to use a StringReader (or something similar) for unit tests etc, there won't be any difficulties.

Personally I always use the "read a line until it's null" approach - sometimes via an extension method so that I can use

foreach (string line in reader.EnumerateLines())
{
}

EnumerateLines would then be an extension method on TextReader using an iterator block. (This means you can also use it for LINQ etc easily.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Nice catch with the Unit Testing. +1 – eandersson Nov 08 '11 at 08:35
  • That is a good point. I like the extension method idea, but I'll probably be switching away from the config files when I begin running test cases. – MattMacdonald Nov 09 '11 at 07:03
  • @MattMacdonald: That's good in terms of testing code that *uses* the configuration (which I assume you have a useful object model for) - but what about testing the code which loads the configuration file? :) – Jon Skeet Nov 09 '11 at 07:27
3

Or you could use ReadAllLines, to simplify your code:

http://msdn.microsoft.com/en-us/library/s2tte0y1.aspx

This way, you let .NET take care of all the EOF/EOL management, and you focus on your content.

jv42
  • 8,521
  • 5
  • 40
  • 64
  • 3
    That does tie you to reading a *file* though. It's nice to be able to pass a `TextReader` into code which deals with the actual logic - that way you can unit test with a `StringReader`. – Jon Skeet Nov 08 '11 at 08:30
  • TextReader has ReadToEnd() which kinda does the same thing. I was thinking about doing that but it still doesn't really simplify my code that much. – MattMacdonald Nov 09 '11 at 06:49
1

No you wont experience any issue's. If you look at the implementation if EndToStream, you'll find that it just checks if there is still data in the buffer and if not, if it can read more data from the underlying stream:

public bool EndOfStream
{
    get
    {
        if (this.stream == null)
        {
            __Error.ReaderClosed();
        }
        if (this.charPos < this.charLen)
        {
            return false;
        }
        int num = this.ReadBuffer();
        return num == 0;
    }
}

Ofcourse casting in your code like that makes it dependend on StreamReader being the actual type of your reader which isn't pretty to begin with.

Polity
  • 14,734
  • 2
  • 40
  • 40
0
            var arpStream = ExecuteCommandLine(cmd, arg);
            arpStream.ReadLine(); // Read entries
            while (!arpStream.EndOfStream)
            {
                var line1 = arpStream.ReadLine().Trim();
                //   TeststandInt.SendLogPrint(line, true);
            }
Kobi Edri
  • 9
  • 5
0

Well, StreamReader is a specialisation of TextReader, in the sense that StreamReader inherits from TextReader. So there shouldn't be a problem. :)

Leonard
  • 3,012
  • 2
  • 31
  • 52
0

Maybe read it all into a string and then parse it: StreamReader.ReadToEnd()

using (StreamReader sr = new StreamReader(path)) 
{
  //This allows you to do one Read operation.
  string contents = sr.ReadToEnd());
}
RvdK
  • 19,580
  • 4
  • 64
  • 107