C# BinaryReader end of Stream

1k Views Asked by At

I am wondering if it's a good practice to use the EndOfStreamException to detect the end of the BinaryReader stream> I don't want to use BaseStream.Length property or PeekChar as proposed here

C# checking for binary reader end of file

because I have to load it into memory (maybe because it's from Zip file) and enable some flags. Instead, this is what I'm doing:

using (ZipArchive zipArchive = ZipFile.OpenRead(Filename))
  using (BinaryReader fStream = new BinaryReader(zipArchive.Entries[0].Open()))
  {
    while(true){
    try
    {
      fStream.ReadInt32();
    }
    catch (EndOfStreamException ex)
    {
      Log.Debug("End of Binary Stream");
      break;
    }
}

}

3

There are 3 best solutions below

1
David Browne - Microsoft On BEST ANSWER

That approach is fine. If you know you have a seekable stream you can compare its length to the number of bytes read. Note that FileStream.Length does not load the whole stream into memory.

But that approach is appropriate for arbitrary streams.

And don't worry about the cost of using exceptions in this case, as streams imply IO, and IO is orders of magnitude slower that exception handling.

5
JonasH On

I would argue that 'best practice' is to have the number of values known, for example by prefixing the stream with the number of values. This should allow you to write it like

var length = fStream.ReadInt32();
for(var i = 0; i < length-1; i++){
    fStream.ReadInt32(); // Skip all values except last
}
return fStream.ReadInt32(); // Last value

First of all this would reduce the need of exception handling, if you reach the endOfStream before the last item you know the stream was incorrectly saved, and have a chance of handling it, instead of just returning the last available value. I also find it helpful to have as few exceptions as possible, so you can run your debugger with "break with thrown", and have some sort of confidence that thrown exceptions indicate actual problems. It can also allow you to save your values as part of some other data.

If you cannot change the input format you can still get the uncompressed length of the entry from ZipArchiveEntry.Length. Just divide by sizeof(int) to get the number of values.

In most cases I would also argue for using a serialization library to save data. This tend to make it much easier to change the format of the data in the future.

1
GOGO DIDN On

check your program or init value.