如何从流中读取n个字节?

maf*_*afu 9 .net c# stream

这比我想象的要复杂一些.我正在尝试从流中读取n个字节.

MSDN声称,上面写着不必返回n个字节,它只是必须返回至少1和n个字节,以0字节是到达流的末尾的特殊情况.

通常,我正在使用类似的东西

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

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

yield return buf;
Run Code Online (Sandbox Code Playgroud)

我希望确切的size字节,但通过规范FileStream也将允许返回大量的1字节块.必须避免这种情况.

解决这个问题的一种方法是使用2个缓冲区,一个用于读取,一个用于收集块,直到我们获得所请求的字节数.虽然这有点麻烦.

我也看了一下BinaryReader但它的规范也没有明确说明肯定会返回n个字节.

澄清一下:当然,在流结束时,返回的字节数可能小于size- 这不是问题.我只是谈论不接收n个字节,即使它们在流中可用.

And*_*tan 15

一个稍微可读的版本:

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

或者写为类的扩展方法Stream:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 12

只是; 你循环;

int read, offset = 0;
while(leftToRead > 0 && (read = stream.Read(buf, offset, leftToRead)) > 0) {
    leftToRead -= read;
    offset += read;
}
if(leftToRead > 0) throw new EndOfStreamException(); // not enough!
Run Code Online (Sandbox Code Playgroud)

在此之后,buf应该已经从流中填充了正确数量的数据,或者已经抛出了EOF.