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

Greg Young [MVP]

March 2008 - Posts

  • 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 }

  • A Passing Thought

    In a long email I wrote tonight I wrote a few words that should stay in every developer's mind and to me personally they represent a step in my own evolution....  for those who have known me for years (Craig, Brian, Steve, Toby, others).

     

     

    Good, even great software will never make money, it can only save money. It can nearly always be done cheaper, more simply to produce the same results.

     

    Businesses survive by making money.

     

    Good even great software is not necessary for a successful business.

     

     

     

    We focus an incredible amount of our time on how to make "great" software .. How to make it maintainable, scalable, and performant.

     

    Thinking back ... my most successful pieces of code have been complete hacks that others can easily attest to.

     

    Two in particular come to mind:

    Toby: The vacuum process and remote updating of sql databases in systems. We spent what 1-2 days on both? Neither were well thought out/scalable but they were probably the most valuable features delivered.

    My entire current system. I spoke about it at QCon a bit but we completed it in 12 days ... we later spent 11 months to do it 'right'. It was a complete hack but it made money.

     

     

    80+% of systems fail for non-technical reasons (bad or late ideas, bad management, political failures) ... Why are we so focused on the technical reasons?

    The only technical failures I have ever seen that needed to be fixed were of already successful systems. How many similar systems failed to the one that succeeded.

     

    It is a calculated risk, but one that should be thought of.

More Posts