12

BinaryReader does not have EndOfStream property. Is it safe to use following code to check if end of stream is reached?

reader.BaseStream.Length>reader.BaseStream.Position

melmi
  • 988
  • 3
  • 9
  • 27

5 Answers5

10

The easiest way I found is to check the returned value of the BinaryReader's PeekChar() method. If it returns -1, then you reached the end of the stream.

Alex Barac
  • 109
  • 2
  • 1
    This works unless the underlying Stream doesn't support seeking. – Waylon Flinn Jun 15 '11 at 19:25
  • Yes, I also found out that in practice, if you call 'PeekChar()' often, it can be extremely slow when dealing with files. – Joannes Vermorel Jul 10 '13 at 07:29
  • 1
    As well, it seems to throw an exception if the data at that position happens to be an invalid character. I sometimes get this: `System.ArgumentException: The output char buffer is too small to contain the decoded characters, encoding 'Unicode (UTF-8)' fallback 'System.Text.DecoderReplacementFallback'.` – Connor Clark Feb 22 '15 at 07:02
7

It depends. There are various stream types that do not implement the Length or Position property, you'd get a NotSupportedException. NetworkStream for example. Of course, if you'd use such a stream then you really do have to know up front how often to call the BinaryReader.Read() method. So, yes, it's fine.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    This isn't universal... There might be a situation when you need to read to the end of a NetworkStream (which happens when the other side closes the connection). – torvin Jul 24 '11 at 09:17
  • Expectation is that the other side says goodbye nicely. If it doesn't then the exception you get when you continue to read from a closed connection is certainly universal. – Hans Passant Jun 28 '17 at 11:07
3

This won't work as a general solution because it assumes that the BaseStream value supports the Length property. Many Stream implementation do not and instead throw a NotSupportedException. In particular any networking base stream such as HttpRequestStream and NetworkStream

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
1

I've noticed that comparing Position to Length DOES NOT work on StreamReader even if the underlying BaseStream supports seeking. It seems that StreamReader buffers read-ahead from the BaseStream. This must be why StreamReader supplies an EndOfStream property, which is a good thing, and I wish BinaryReader did the same.

Checking these values (Length and Position) on the underlying base stream counts on BinaryReader to not behave as StreamReader does, i.e. relies on BinaryReader only grabbing the exact number of bytes from BaseStream needed to fulfill a user method call. Presumably if BinaryReader in fact operates this way internally it is why it does not need to supply an EndOfStream, but I sure wish it did supply one so that I knew that end of file was being correctly handled for clients in an implementation independent way.

Of course Readers are not Streams, but with respect to end of file behavior it would be nice if there were a common interface that enabled clients of input/output classes to know if A. end of file is a sensible concept for the underlying source of data, and B. when end of file occurs if A is sensible.

0

Check the Streams CanSeek property. If this property returns true then you can compare the streams Length to the stream's Position to tell if you are at the end of the stream. If this property returns false then this won't work.

For Network streams you may need to distinguish between the end of the available bytes (the client on the other end still have more to write but hasn't yet) and the stream being closed. The IsConnected property for an underlying Tcp connection isn't reliable for knowing when the stream has closed. It is possible to enumerate the connections that the computer has and see if the stream you are using is among them. This is more reliable, but more complex. It may be better to just handle IOExceptions when you can't read any

Joel
  • 2,230
  • 1
  • 20
  • 28