Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the offset in a stream

Tags:

c#

.net

stream

It says here msdn.microsoft.com/en-us/library/system.io.stream.read.aspx that the Stream.Read and Stream.Write methods both advance the position/offset in the stream automatically so why is the examples here http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx and http://msdn.microsoft.com/en-us/library/system.io.filestream.read.aspx manually changing the offset?

Do you only set the offset in a loop if you know the size of the stream and set it to 0 if you don't know the size and using a buffer?

   // Now read s into a byte buffer.
    byte[] bytes = new byte[s.Length];
    int numBytesToRead = (int) s.Length;
    int numBytesRead = 0;
    while (numBytesToRead > 0)
    {
        // Read may return anything from 0 to 10.
        int n = s.Read(bytes, numBytesRead, 10);
        // The end of the file is reached.
        if (n == 0)
        {
            break;
        }
        numBytesRead += n;
        numBytesToRead -= n;
    }

and

using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
    const int size = 4096;
    byte[] buffer = new byte[size];
    using (MemoryStream memory = new MemoryStream())
    {
    int count = 0;
    do
    {
        count = stream.Read(buffer, 0, size);
        if (count > 0)
        {
        memory.Write(buffer, 0, count);
        }
    }
    while (count > 0);
    return memory.ToArray();
    }
}
like image 952
Jonas Avatar asked Oct 16 '11 21:10

Jonas


2 Answers

The offset is actually the offset of the buffer, not the stream. Streams are advanced automatically as they are read.

like image 115
user1007672 Avatar answered Oct 28 '22 23:10

user1007672


Edit (to the edited question):

In none of the code snippets you pasted into the question I see any stream offset being set.

I think you are mistaking the calculation of bytes to read vs. bytes received. This protocol may seem funny (why would you receive fewer bytes than requested?) but it makes sense when you consider that you might be reading from a high-latency packet oriented source (think: network sockets).

You might be receiving 6 characters in one burst (from a TCP packet) and only receive the remaining 4 characters in your next read (when the next packet has arrived).

Edit In response to your linked example from the comment:

using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
    { 
       // ... snip

        count = stream.Read(buffer, 0, size);
        if (count > 0)
        {
        memory.Write(buffer, 0, count);
        }

It appears that the coders use prior knowledge about the underlying stream implementation, that stream.Read will always return 0 OR the size requested. That seems like a risky bet, to me. But if the docs for GZipStream do state that, it could be alright. However, since the MSDN samples use a generic Stream variable, it is (way) more correct to check the exact number of bytes read.


The first linked example uses a MemoryStream in both Write and Read fashion. The position is reset in between, so the data that was written first will be read:

    Stream s = new MemoryStream();
    for (int i = 0; i < 100; i++)
    {
        s.WriteByte((byte)i);
    }
    s.Position = 0;

The second example linked does not set the stream position. You'd typically have seen a call to Seek if it did. You maybe confusing the offsets into the data buffer with the stream position?

like image 34
sehe Avatar answered Oct 29 '22 00:10

sehe