Combine Streams In A Single C# Stream Object

This article represents a simple Stream class whose data is based on the number of another .NET Framework streams.

There are sometasks when you may want to provide the data combined from differentparts via Stream interface. The most obvious way is to create theMemoryStream class instance and copy all data parts (streams in ourcase) into this single object. This solution has only one good thing -the simplicity and you can use it for sure for combining of smallfootprint streams without bothering about the reverse of the medal.While working with the large size streams or having big number ofstreams such primitive copying of data chunks may lead to badapplication performance and irrational using of virtual memory.

MultiStream Class Declaration

In order toeffectively combine number of streams into the single Stream classdescendant you will need to organize access to streams data inappropriate order.

We will create new MultiStream inherited from .NET base abstract Stream class. Methods ReadSeekWrite and also Length property need to be overriden and implemented within MultiStream class. Allremaining abstract Stream members have the obvious implementation andto be shortest we do not place them here. But you can find the fullsource code for this class at multistreamcs.zip

The code below shows the implementation of the Read method of MultiStream class:

public override int Read(byte[] buffer, int offset, int count) {
   long len = 0;
   int result = 0;
   int buf_pos = offset;
   int bytesRead;
   foreach(Stream stream in streamList) {
      if(position < (len + stream.Length)) {
         stream.Position = position – len;
         bytesRead = stream.Read(buffer, buf_pos, count);
         result += bytesRead;
         buf_pos += bytesRead;
         position += bytesRead;
         if(bytesRead < count) {
            count -= bytesRead;
         }
         else {
            break;
         }
      }
      len += stream.Length;
   }
   return result;
}

This method walksthrough all streams being stored within the streamList member ofMultiStream class and checks each of them for matching the MultiStreamPosition. If the current stream position plus total all of the previousstreams sizes matches to the main Position then data from this streamwill be transferred until requested buffer size extends up to theanother stream items.

The Seek method implements locating of the TMultiStream Position pointer using the total size of collected stream items:

public override long Seek(long offset, SeekOrigin origin) {
   long len = Length;
   switch(origin) {
      case SeekOrigin.Begin:
         position = offset;
         break;
      case SeekOrigin.Current:
         position += offset;
         break;
      case SeekOrigin.End:
         position = len – offset;
         break;
   }
   if(position > len) {
      position = len;
   }
   else if(position < 0) {
      position = 0;
   }
   return position;
}

Please note that the contents of the MultiStream can not be modified by calling of Write method. So implementation of this method will be very simple:

public override bool CanWrite {
   get { return false; }
}

Indeed it is quite difficult to imagine such task when you might need to change the contents of the multistream object.

Using of MultiStream Class

With just few lines of code the new MultiStream class is ready to use. Lets go ahead and test it:

="100%">MultiStream stream = new MultiStream();
stream.AddStream(new StringStream("test string "));
stream.AddStream(new FileStream("testfile.txt", FileMode.Open, FileAccess.Read, FileShare.Read));
byte[] buf = new byte[1024];
int cnt = stream.Read(buf, 0, 1024);
Debug.Assert(new ASCIIEncoding().GetString(buf, 0, cnt).Equals("test string test file"));

The full source code of classes being used in this article can be downloaded at multistreamcs.zip

This code is constantly being improved and your comments and suggestions are always welcome.

With best regards,
Sergey S 
Clever Components team.

Most Commented Articles :

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!