Using Stream.Read() vs BinaryReader.Read() to process binary streams
One big difference is how you can buffer the I/O. If you are writing/reading only a few bytes here or there, BinaryWriter/BinaryReader
will work well. But if you have to read MBs of data, then reading one byte
, Int32
, etc... at a time will be a bit slow. You could instead read larger chunks and parse from there.
Example:
// Using FileStream directly with a buffer
using (FileStream stream = new FileStream("file.dat", FileMode.Open))
{
// Read bytes from stream and interpret them as ints
byte[] buffer = new byte[1024];
int count;
// Read from the IO stream fewer times.
while((count = stream.Read(buffer, 0, buffer.Length)) > 0)
for(int i=0; i<count; i++)
Console.WriteLine(Convert.ToInt32(buffer[i]));
}
Now this is a bit off topic... but I'll throw it out there:
If you wanted to get VERY crafty... and really give yourself a performance boost... (Albeit, it might be considered dangerous) Instead of parsing EACH Int32
, you could do them all at once using Buffer.BlockCopy()
Another example:
// Using FileStream directly with a buffer and BlockCopy
using (FileStream stream = new FileStream("file.dat", FileMode.Open))
{
// Read bytes from stream and interpret them as ints
byte[] buffer = new byte[1024];
int[] intArray = new int[buffer.Length >> 2]; // Each int is 4 bytes
int count;
// Read from the IO stream fewer times.
while((count = stream.Read(buffer, 0, buffer.Length)) > 0)
{
// Copy the bytes into the memory space of the Int32 array in one big swoop
Buffer.BlockCopy(buffer, 0, intArray, count);
for(int i=0; i<count; i+=4)
Console.WriteLine(intArray[i]);
}
}
A few things to note about this example: This one takes 4 bytes per Int32 instead of one... So it will yield different results. You can also do this for other data types other than Int32, but many would argue that marshalling should be on your mind. (I just wanted to present something to think about...)
No, there is no principal difference between the two approaches. The extra Reader adds some buffering so you shouldn't mix them. But don't expect any significant performance differences, it's all dominated by the actual I/O.
So,
- use a stream when you have (only)
byte[]
to move. As is common in a lot of streaming scenarios. - use BinaryWriter and BinaryReader when you have any other basic type (including simple
byte
) of data to process. Their main purpose is conversion of the built-in framework types tobyte[]
.