tags:

views:

148

answers:

3

I'm just writing an simple method witch reading data from a general stream - which means it could be possibly a FileStream or a NetworkStream without knowing the length of it. I repeatly read the stream into a byte[] and push the data to another stream or whatever. My question is, how can I notice the stream is finished? I tried to return when the Read method returns 0 - is it the right way to do so? It seems that it's ok for reading files but meet problems for reading data from network, sometimes.

A: 

For network streams, if Stream.ReadByte() returns anything less than 0 you know that the stream was read to the end.

emaster70
Do you mean that I should put a ReadByte() method call right after the Read method in the body of loop for NetworkStream?
Jeffrey Zhao
+4  A: 

Yes, calling Read repeatedly and finishing when it returns 0 is exactly the right way to do it.

Network streams are fine with this as well - they will block until any data is received or the stream is disconnected. Look at the documentation for Stream.Read:

The return value is zero only if the position is currently at the end of the stream. The implementation will block until at least one byte of data can be read, in the event that no data is available. Read returns 0 only when there is no more data in the stream and no more is expected (such as a closed socket or end of file).

Jon Skeet
I stand corrected, thanks.
JoshBerke
Then it seems that we have to know the length of the data for network stream?
Jeffrey Zhao
Knowing the length helps, but it's not strictly necessary.
Mystere Man
For sockets, you really only have two choices: A protocol with a fixed format (I.E. fixed length fields describe the length of variable fields later in the stream), or using delimiters (special characters embedded in the stream that tell you when to stop).
dicroce
Actually, there's a third as well. You might have a fixed length protocol. Ie, all fields are exactly x bytes.
Mystere Man
I'm quite interested in how WebClient class konws that.
Jeffrey Zhao
Even with a fixed length protocol, you still need to take note of the value returned by Read. Just because you *asked* for 100 bytes doesn't mean you'll have *read* 100 bytes.
Jon Skeet
A: 

As Jon says, you know it's the end of file because it will return 0 bytes. However, you must also take into account various exceptions that can be thrown. Because a network is inherantly unreliable, some exceptions will always be possible.

For example, if the stream is disconnected (as opposed to the other side simply closing the socket) then you might receive an IOException exception. Always wrap IO calls in exception handlers, unless you are absolutely certain they can't throw an exception.

Mystere Man
Just because they might throw exceptions doesn't mean you should wrap them in handlers. In my experience, if an IO call throws IOException, the method *making* that call should usually just allow the exception to bubble up. I tend to have very few try/catch blocks - usually just near the top.
Jon Skeet
I didn't mean you have to catch it right away. But it should be caught at some point.
Mystere Man