Living .NET...

Musings on .NET, and the like - Manoj G [MVP, Connected Systems Developer]

March 2005 - Posts

Stream Quips & Traps

I was working with SoapExtensions and my project involved a lot of reading and writing to streams (Yes, in the ProcessMessage method of the SoapExtension). I came across this good article by Jon Skeet which explains the reading of binary data from the stream. This article basically explains the best ways of using the Read method of the stream and also mentions about the potential errors that might creep up when Stream.Read is used incorrectly. A related task is to copy the contents of one stream to another. Here's one of the ways of doing this:

static void CopyStream(Stream inStream, Stream outStream) {
    
byte[] buf = new byte[1024];
    
int size = 1024;
    
int count = 0;
    
    count = inStream.Read(buf,0,size);
    
while (count > 0) {
      outStream.Write(buf,0,count);
      count = inStream.Read(buf,0,size);
    }
    outStream.Flush();
 }

A more simple looking helper would involve the StreamReader and the StreamWriter as shown here:

static void CopyStream(Stream from, Stream to) 
{
   TextReader reader = 
new StreamReader(from);
   TextWriter writer = 
new StreamWriter(to);
   writer.WriteLine(reader.ReadToEnd());
   writer.Flush();
}

Of course, if you 'reflect' the implementation behind these, you would find them to be very similar to the first CopyStream method. What is evident from this example is that it is definitely easier to use StreamReader and StreamWriter over using Stream directly. Also, you can work with strings directly as against using a byte array.

I shall conclude this post by mentioning a few traps that one can usually fall into while using the Stream class. By definition, a stream is plainly, a sequence of bytes. The stream is read from start to finish in a serial fashion (unless you do a seek operation) and the Position property provides the position where the current byte has to be read. Therefore, any operation involving the reading of the entire contents of the stream (like StreamReader.ReadToEnd, for instance) would shift the position past the last byte read. So, reading the stream without resetting the position to zero causes erroneous behavior (I tried to load an XmlDocument using the Load method and I constantly kept getting "Root Element missing error"!)

Another aspect to keep in mind is that most streams (MemoryStream is an exception) are buffered. Writing data to the stream does not mean that the data is transferred to the underlying media or device. We would need to call the Flush method to ensure the same. Again StreamWriter provides an AutoFlush property which can be used when buffering semantics are not really required.

Happy 'Stream'ing!

Posted: Tue, Mar 22 2005 14:19 by Manoj G | with no comments
Filed under: