tags:

views:

334

answers:

5

Suppose we have a code block like this :

//Assuming s is a stream:
byte[] data = new byte[1000];
s.Read(data,0,data.Length);

The read Method could read anywhere from 1 to 1000 bytes, leaving the balance of the stream unread.

This is what a C# book says.

I don't understand,why Read method would read anywhere from the stream ? It ain't reading all of the stream ?

And it says the work-around should be like this :

//bytesRead will always end up at 1000, unless the stream is itself smaller in length:
int bytesRead = 0;
int chunkSize = 1;
while(bytesRead < data.Length && chunkSize > 0 )
      bytesRead += chunkSize = s.Read(data,bytesRead,dataLength-bytesRead);

This code above is also provided by the book as a work-around. What I am trying to understand whether Read method is beginning to read to the end and write all of the bytes in specified range to byte array. Why is he using the bytesRead as a start point in s.Read(data,bytesRead,dataLength-bytesRead);

Thanks in advance.

+4  A: 

The idea is that the data may not be available at the time you call Read... or ever. For example, on a NetworkStream, the data may be arriving more slowly than you are picking it up. Or you might be close to the end of a FileStream. The Stream may know that there are fewer bytes remaining than you asked for, or it may have no way of knowing when or whether the full whack of requested bytes will arrive. So rather than wait for data that may never arrive, or fail with a "not enough bytes, guess again" error, Read reserves the right to return less than you asked for.

Consequently, when reading a chunk into a byte array, you may not be filling the byte array. But you want the next chunk to be appended where the last one left off, rather than overwriting the beginning of the byte array. Hence passing bytesRead as the starting location for placing the next chunk in the byte array.

itowlson
A: 

Based on my reading of the documentation for the Read method, because streams can be used to read widely varying data sources, from keyboard input to files to network traffic, it has been left open to the specific implementation whether data returned by the read method will return the requested number of bytes. For example, if a particular implementation for reading network data wants to return the 500 bytes of data that's available so far for a web request, but it expects that it won't be done until it reads 1000 bytes, and you've requested 1000 bytes, it may return what it has so you can process it. It will tell you that it only read 500 bytes, and you should be aware that there may be more on the way. The 1000 maximum is just an indication that you don't want to process more than 1000 bytes at a time.

BlueMonkMN
+1  A: 

The first example is using the byte array's declared size of 1000 as an input parameter into the Read method.

The second example is reading the stream one byte at a time, which is great for streaming incoming or outgoing data - meaning if you can process portions of the stream you are receiving without first buffering it all entirely into memory this is a more efficient approach.

I think where you are getting confused here is that the author is artificially limiting the example to 1,000 bytes maximum. A lot of protocols that involve streaming usually send a byte or two at the beginning specifically notifying the consumer of the length of the stream as a whole so it can best chunk and process the stream so no declared limit of 1,000 is required. You get the size, you chunk it appropriately (including the last chunk which may not be complete chunk size), and process each chunk.

cfeduke
You mean, first they send the size of the data they want to send and then they send the whole data as chunks instead of sending it as a whole ?
Braveyard
Usually yes. Let's say you have a 40 MB file on disk you want to transfer. Rather than loading 40 MB in memory then transferring it - and thus making 40 MBs of memory crowded for a length of time - you just read, let's say the first 1024 bytes, transfer it, and continue in 1024 byte chunks. A file transfer protocol may state "the first two bytes of the first packet contains an unsigned int indicating the size of the payload" so you know when to stop reading from that stream. The receiving end can do the same - chunk it into 1024 bytes or some other resource friendly buffer number.
cfeduke
A: 

I don't understand,why Read method would read anywhere from the stream ? It ain't reading all of the stream ?

Read allows you to specify start and endpoints for reading. See itowlson's answer for more information.

What I am trying to understand whether Read method is beginning to read to the end and write all of the bytes in specified range to byte array.

If this was a question I suppose the answer is no. The Read method fills an array with data from a stream at the specified start and end points.

Why is he using the bytesRead as a start point in s.Read(data,bytesRead,dataLength-bytesRead);

He is using bytesRead to keep track of "the amount of bytes read". This lets him know where to start reading on the next Read call.

Ragepotato
+1  A: 

The phrase "could read anywhere from 1 to 1000 bytes" means "could read 1 byte, or 2 bytes, up to 1000 bytes". It refers to the length of bytes read, not the location. The read will be located at the stream's current position.

Skirwan