Question

When I'm using a Text reader what is the best way to detect that I am actually at the end of my data? The usual way to do this is something like the following,

    while(reader.Peek() != -1)
    {
       ///do stuff
    }

However the msdn documentation here states the following

An integer representing the next character to be read, or -1 if no more characters are available or the reader does not support seeking.

So my question is how do you tell if you are really at the end of the readers data or the reader/underlying stream simply doesn't support seeking as the return value here seems to be ambiguous? if for example I have the following

    public void Parse(TextReader reader)
    {
         while(reader.Peek() != -1) //am I really at the end
         {
            //do stuff
         }
    }

    Parse(new StreamReader(new NetworkStream(....)));

as networkstream does not support seeking.

Or have I missed something?

Edit:

Just to clarify, I can easily implement this using the more specific StreamReader class, as I can check for EoS. However to keep things more general, I wanted to use TextReader so I am not tied to just StreamReader. However the semantics of Peek seem a little odd, why does it not just throw if seeking isnt supported, and to this end why isn't there an EoF property for TextReader?

Was it helpful?

Solution 2

It really depends on what you're doing in the parse.

I would usually just Read, and see how much is read. I would suggest not reading a character at a time though:

char[] buffer = new char[1024 * 16];
int charsRead;
while ((charsRead = read.Read(buffer, 0, buffer.Length)) > 0)
{
    // Process buffer, only as far as charsRead
}

OTHER TIPS

unless you are looking for a specific value using Peek() why not use .Read()

for example

string line;
System.IO.StreamReader file = new System.IO.StreamReader(strfn);
while((line = file.ReadLine()) != null)
{
  this.richTextBox1.AppendText(line+"\n");//you can replace this line to fit your UseCase
}

If you want a Cleaner example of how this could be done you could do something like what I have posted below it readable and you can plug in your own text file values and Debug this to see that it will work. Reading and Writing

string tempFile = Path.GetTempFileName();
using(var sr = new StreamReader("file.txt"))
{
  using(var sw = new StreamWriter(tempFile))
  {
    string line;
    while((line = sr.ReadLine()) != null)
    {
         if(line != "BlaBlaBla")
             sw.WriteLine(line);
    }
  }
}

Here is another option you could try

From a Stream, if you Read(buffer, offset, count) you'll get a non-positive result, and if you Peek() you'll get a negative result.

With a BinaryReader, the documentation suggests that PeekChar() should return negative:

Return Value

Type: System.Int32 The next available character, or -1 if no more characters are available or the stream does not support seeking.

are you sure this isn't a corrupt stream? i.e. the remaining data cannot form a complete char from the given encoding?

It should be reader.Read() == -1 no more or else character exists.

If you simply need to read and process all data till the end of your stream, then you should use Read directly, which returns -1 if no more characters are available.

int nextByte;
while ((nextByte = reader.ReadByte()) != -1)
    // Process nextByte here.

Edit: An alternative way of checking specifically whether the reader supports seeking is to check the underlying stream:

bool canSeek = reader.BaseStream.CanSeek;

If this returns true, then Peek should only return -1 when the end of the stream is reached.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top