How do I read exactly n bytes from a stream?

This is a little more complicated than I imagined. I am trying to read n bytes from a stream.

MSDN claims that Read should not return n bytes, it should simply return at least 1 and up to n bytes, with 0 bytes being a special case of reaching the end of a stream.

I usually use something like

var buf = new byte[size]; var count = stream.Read (buf, 0, size); if (count != size) { buf = buf.Take (count).ToArray (); } yield return buf; 

I hope to get exactly size bytes, but according to the specification FileStream will be allowed to return a large number of 1-byte blocks. This should be avoided.

One way to resolve this issue is to have 2 buffers, one for reading and one for collecting chunks, until we get the requested number of bytes. It's a little cumbersome though.

I also looked at BinaryReader , but its specification also did not explicitly indicate that n bytes would be returned exactly.

To clarify: Of course, at the end of the stream, the returned number of bytes may be less than size - this is not a problem. I am only talking about not getting n bytes, even if they are available in the stream.

+7
source share
2 answers

A slightly more readable version:

 int offset = 0; while (offset < count) { int read = stream.Read(buffer, offset, count - offset); if (read == 0) throw new System.IO.EndOfStreamException(); offset += read; } 

Or written as an extension method for the Stream class:

 public static class StreamUtils { public static byte[] ReadExactly(this System.IO.Stream stream, int count) { byte[] buffer = new byte[count]; int offset = 0; while (offset < count) { int read = stream.Read(buffer, offset, count - offset); if (read == 0) throw new System.IO.EndOfStreamException(); offset += read; } System.Diagnostics.Debug.Assert(offset == count); return buffer; } } 
+11
source

Just; you are executing a loop;

 int read, offset = 0; while(leftToRead > 0 && (read = stream.Read(buf, offset, leftToRead)) > 0) { leftToRead -= read; offset += read; } if(leftToRead > 0) throw new EndOfStreamException(); // not enough! 

After that, buf should be filled with exactly the right amount of data from the stream or EOF will be thrown.

+9
source

All Articles