mnn
mnn

Reputation:

Inherited Stream; buffering in Read()

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!

Upvotes: 3

Views: 1540

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1062550

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);
}

Upvotes: 1

AnthonyWJones
AnthonyWJones

Reputation: 189437

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

Upvotes: 0

Related Questions