Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
592 views
in Technique[技术] by (71.8m points)

c# - How do I read exactly n bytes from a stream?

This is a little more tricky than I first imagined. I'm trying to read n bytes from a stream.

The MSDN claims that Read does not have to return n bytes, it just must return at least 1 and up to n bytes, with 0 bytes being the special case of reaching the end of the stream.

Typically, I'm using something like

var buf = new byte[size];
var count = stream.Read (buf, 0, size);

if (count != size) {
    buf = buf.Take (count).ToArray ();
}

yield return buf;

I'm hoping for exactly size bytes but by spec FileStream would be allowed to return a large number of 1-byte chunks as well. This must be avoided.

One way to solve this would be to have 2 buffers, one for reading and one for collecting the chunks until we got the requested number of bytes. That's a little cumbersome though.

I also had a look at BinaryReader but its spec also does not clearly state that n bytes will be returned for sure.

To clarify: Of course, upon the end of the stream the returned number of bytes may be less than size - that's not a problem. I'm only talking about not receiving n bytes even though they are available in the stream.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

A slightly more readable version:

int offset = 0;
while (offset < count)
{
    int read = stream.Read(buffer, offset, count - offset);
    if (read == 0)
        throw new System.IO.EndOfStreamException();
    offset += read;
}

Or written as an extension method for the Stream class:

public static class StreamUtils
{
    public static byte[] ReadExactly(this System.IO.Stream stream, int count)
    {
        byte[] buffer = new byte[count];
        int offset = 0;
        while (offset < count)
        {
            int read = stream.Read(buffer, offset, count - offset);
            if (read == 0)
                throw new System.IO.EndOfStreamException();
            offset += read;
        }
        System.Diagnostics.Debug.Assert(offset == count);
        return buffer;
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...