C# - Stream.Read 偏移量工作不正确

问题描述

我有一个如下所示的测试代码。我正在从流中读取,偏移 2 个位置,然后取下 2 个字节。我希望结果是一个包含 2 个元素的数组。但这不起作用 - 完全忽略偏移量,并且始终返回完整大小的数组,只有偏移块具有值。 但这意味着我的结果表仍然很大,它只是有很多不需要的零

如何修改下面的代码,以便 file.Read() 在长度 = 2 且偏移量 = 2 时仅返回 2 个字节而不是 10 个字节的数组?在现实世界场景中,我正在处理大文件(> 2gigs),因此不能选择过滤结果数组。

编辑:由于问题不清楚 - 下面的代码要求我始终定义与流大小相同的输出数组。相反,我想要一个大小为 length输出(在下面的示例中,我想要var buffer = new byte[2],但这会引发异常,因为 file.Read 忽略偏移量和长度并始终返回10 个元素(只有 2 个被读取,其余是虚拟零)。

        private byte[] GetFilePart(int length,int offset)
        {
            //build some dummy content
            var content = new byte[10];
            for (int i = 0; i<10; i++)
            {
                content[i] = 1;
            }

            //read the data from content
            var buffer = new byte[10];
            using (Stream file = new MemoryStream(content))
            {
                file.Read(buffer,offset,length);
            }
            return buffer;
        }

offset not working

解决方法

看起来它对我来说工作正常;如果您使用以下内容初始化内容数组,也许您的困惑会有所缓解:

        for (int i = 1; i<=10; i++)
        {
            content[i-1] = i;
        }

然后每个字节会有不同的数字,图像看起来像: enter image description here

offsetbuffer 将字节写入 Stream 的位置有关(它从 content 的开头读取)。它与从 content 中读出的字节无关。

想象一下 Read 被称为 WriteBytesInto(byte[] whatBuffer,int whereToStartWriting,int howManyBytesToWrite) - 您提供它将写入的缓冲区并告诉它从哪里开始以及要执行多少

如果你这样做了,初始化 content 来增加数字:

file.Read(buffer,2,3); //read 3 bytes from stream and write to buffer @ index 2
file.Read(buffer,2); //read 2 bytes from stream and write to buffer @ index 0

你的缓冲区最终看起来像:

4,5,1,3,0

先写了 1,3,然后写了 4,5


如果您想从流中跳过两个字节(即从 contentSeek() 流中读取第 3 个和第 4 个字节或设置其 Position(或如 canton7 在注释,如果流不可搜索,则读取并丢弃一些字节)

如何修改下面的代码,以便 file.Read() 在 length = 2 和 offset = 2 时仅返回 2 个字节而不是 10 个字节的数组?

好吧,file.Read 根本不返回数组;它修改你给它的数组。如果你想要一个 2 字节的数组,给它一个 2 字节的数组:

byte buf = new byte[2];
file.Read(buf,buf.Length);

如果要打开文件,请跳过前 7 个字节,然后将第 8 个和第 9 个字节读入长度为 2 的字节数组,然后:

byte buf = new byte[2];
file.Position = 7; //absolute skip to 8th byte
file.Read(buf,buf.Length);

有关在流中查找的更多信息,请参阅 Stream.Seek(0,SeekOrigin.Begin) or Position = 0