views:

128

answers:

3

Hello, I have inherited Stream class, in which I don't know how to implement Read() function properly, so I won't end up with a lot of nested ifs and hard to debug code. The point is that reading from source of this stream returns constant sized buffer (e.g. not changeable), but Read() function accepts different buffer sizes. I though of adding BufferedStream, but I think that's bad idea. Thanks for help!

A: 

The inner source returns fixed-size buffers? If that case, that isn't quite what BufferedStream does - that simply reduces the number of calls to a physical stream. You'd need a separate mechanism to cache - a MemoryStream that you fill and empty would be a reasonable choice. For example (completely untested):

MemoryStream localBuffer = new MemoryStream();
bool ReadNextChunk()
{
    // clear
    localBuffer.Position = 0;
    localBuffer.SetLength(0);
    // get data
    byte[] chunk = null; // TODO - read from source
    if(chunk == null || chunk.Length == 0) return false; // EOF
    localBuffer.Write(chunk, 0, chunk.Length);
    localBuffer.Position = 0;
    return true;
}
public override int Read(byte[] buffer, int offset, int count)
{
    int bytes;
    if ((bytes = localBuffer.Read(buffer, offset, count)) > 0) return bytes;
    if (!ReadNextChunk()) return 0;
    return localBuffer.Read(buffer, offset, count);
}
Marc Gravell
A: 

Here is your "starter for 10" (not sure if that translates globally).

byte[] myBuffer = new byte[fixedSize];
int myBufferPos = fixedSize;

public int Read(byte[] buffer, int offset, int count)
{
 int copiedCount = 0
    while (copiedCount < count)
 {
  if (myBufferPos >= fixedSize)
  {
   //Read new fixed buffer into myBuffer
   // use break on no more buffer.
   myBufferPos = 0;
  }

  int bytesToCopy = fixedSize - myBufferPos;
  if (bytesToCopy > count - copiedCount)
   byteToCopy = count - copiedCount;

  Array.Copy(myBuffer, myBufferPos, buffer, offset, byteToCopy);

  offset += bytesToCopy;
  myBufferPos += bytesToCopy;
  copiedCount += bytesToCopy;
 }

 return copiedCount;
}

Untested so may have some bugs. Its unclear if your source stream has a length of exact multiples of its fixed size. If not then the final partial buffer needs a little extra logic.

The basic principle is to maintain your own buffer of the fixed size and track the position in that buffer so far consumed by reads

AnthonyWJones
+1  A: 

AnthonyWJones: Thanks, but I like more the MemoryStream solution, I hate that Array.Copy stuff :).

Marc Gravell: Thanks for inspiration! Works flawleslly now :D

If this is complete, use the "tick" to mark as answered...
Marc Gravell