CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Greg Young [MVP]


IteratorStream

I had to write this quick little adapter the other day for something and figured it might be useful for people ...

 

In general you are better off making the code that is using a stream not use a stream but to use an IEnumerable<byte []> since using stream you are required to copy ... Buy for very large buffers this is far more efficient than copying into a MemoryStream.

 
 

 

   10 public class IteratorStream : Stream

   11 {

   12     private readonly IEnumerator<byte[]> m_Chunks;

   13     private ArraySegment<byte> m_CurrentChunk;

   14 

   15     public IteratorStream(IEnumerable<byte[]> _Chunks)

   16     {

   17         if (_Chunks == null) throw new ArgumentNullException();

   18         m_Chunks = _Chunks.GetEnumerator();

   19     }

   20 

   21     public override bool CanRead {

   22         get { return true; }

   23     }

   24 

   25     public override bool CanSeek

   26     {

   27         get { return false; }

   28     }

   29 

   30     public override bool CanWrite {

   31         get { return false; }

   32     }

   33     public override long Length { get { return -1; } }

   34 

   35     public override long Position

   36     {

   37         get { throw new NotImplementedException(); }

   38         set{ throw new NotImplementedException();}

   39     }

   40 

   41     private bool ReadNextChunk()

   42     {

   43         bool HasMore = m_Chunks.MoveNext();

   44         if (HasMore)

   45         {

   46             m_CurrentChunk = new ArraySegment<byte>(m_Chunks.Current);

   47         }

   48         return HasMore;

   49     }

   50 

   51     public override int Read(byte[] buffer, int offset, int count) {

   52         if (buffer == null) throw new ArgumentNullException("buffer");

   53         if (offset < 0 || offset >= buffer.Length) throw new ArgumentException("offset must be greater than or equal to 0 and less than the size of the buffer");

   54         if (count < 0) throw new ArgumentException("count must be greater than or equal to 0");

   55         if (offset + count > buffer.Length) throw new ArgumentException("offset + count must be less than the buffer size");

   56 

   57         int LeftToRead = count;

   58         int CurrentLocation = offset;

   59         if (m_CurrentChunk.Count == 0)

   60         {

   61             if (!ReadNextChunk())

   62             {

   63                 return 0;

   64             }

   65         }

   66         while (LeftToRead > 0 && m_CurrentChunk.Count != 0)

   67         {

   68             int toRead = (LeftToRead > m_CurrentChunk.Count) ? m_CurrentChunk.Count : LeftToRead;

   69             Buffer.BlockCopy(m_CurrentChunk.Array, m_CurrentChunk.Offset, buffer, CurrentLocation, toRead);

   70             LeftToRead -= toRead;

   71             CurrentLocation += toRead;

   72             m_CurrentChunk = new ArraySegment<byte>(m_CurrentChunk.Array, m_CurrentChunk.Offset + toRead, m_CurrentChunk.Count - toRead);

   73             if (m_CurrentChunk.Count == 0)

   74             {

   75                 ReadNextChunk();

   76             }

   77         }

   78         return count - LeftToRead;

   79     }

   80 

   81     protected override void Dispose(bool disposing)

   82     {

   83         base.Dispose(disposing);

   84         if (disposing && m_Chunks != null)

   85         {

   86             m_Chunks.Dispose();

   87         }

   88 

   89     }

   90 

   91     public override long Seek(long offset, SeekOrigin loc) { throw new NotImplementedException(); }

   92     public override void SetLength(long value) { throw new NotImplementedException(); }

   93     public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); }

   94     public override void Flush() { throw new NotImplementedException(); }

   95     public override void WriteByte(byte value) { throw new NotImplementedException(); }

   96 }

   97 

   98 

   99 class Program

  100 {

  101     static IEnumerable<byte[]> GetBytes()

  102     {

  103         byte [] OneToTen = new byte[10];

  104         for(byte i=0;i<10;i++)

  105             OneToTenIdea = i;

  106         for(int j = 0;j <10;j++) {

  107             yield return OneToTen;

  108         }

  109     }

  110 

  111     static void Main(string[] args)

  112     {

  113         IteratorStream stream;

  114         using (stream = new IteratorStream(GetBytes()))

  115         {

  116             int read = stream.ReadByte();

  117 

  118             //read 1 byte at a time

  119             while (read != -1)

  120             {

  121                 Console.WriteLine(read.ToString());

  122                 read = stream.ReadByte();

  123             }

  124         }

  125 

  126         //read 100 bytes

  127         using (stream = new IteratorStream(GetBytes()))

  128         {

  129             byte[] buffer = new byte[100];

  130             int read = stream.Read(buffer, 0, 100);

  131             Console.WriteLine(read);

  132         }

  133 

  134     }

  135 }



Comments

Shawn Wildermuth said:

This is cool but the code is a mess because of the host being smart about smiley's and such. Do you think you could provide it as a downloadable .cs?
# March 27, 2008 2:09 PM

Greg said:

Here is the URL to the code ... just put into a quick console application

codebetter.com/.../entry175969.aspx

# March 27, 2008 2:29 PM

friend said:

plz post your code snippets at www.codekeep.net

# March 27, 2008 4:45 PM

Dew Drop - March 28, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - March 28, 2008 | Alvin Ashcraft's Morning Dew

# March 28, 2008 9:38 AM

Jason Haley said:

# March 28, 2008 10:13 AM

Greg said:

To the person asking for email ... you can reach me at grzegoryzyozung1 at gmail

remove the z's

# March 29, 2008 3:57 PM

Charlie Calvert's Community Blog said:

Welcome to the forty-second issue of Community Convergence. The last few weeks have been a busy time

# March 31, 2008 12:56 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!