11

由于 BinaryReader 的底层缓冲策略,我不清楚是否可以读取存储在流中的偏移量,然后在该偏移量处重新定位流以恢复流式传输。

例如,以下代码是否可以:

using (var reader = new CustomBinaryReader(inputStream))
{
   var offset= reader.ReadInt32();
   reader.BaseStream.Seek(offset, SeekOrigin.Begin);

   //Then resume reading the streaming
}

或者我应该在寻找流之前关闭第一个二进制阅读器,然后重新打开第二个阅读器?

int offset;
using (var firstReader = new CustomBinaryReader(inputStream))
{
   offset= firstReader.ReadInt32();
}
inputStream.Seek(offset, SeekOrigin.Begin);
using (var secondReader = new CustomBinaryReader(inputStream))
{
   //Then resume reading the streaming
}
4

3 回答 3

11

BinaryReader 确实使用缓冲区,但仅从基本流中读取足够的字节来转换值。换句话说,ReadInt32() 将首先缓冲 4 个字节,ReadDecimal() 将首先缓冲 16 个字节,等等。ReadString() 是比较棘手的方法,但它也有对策,一个字符串由 BinaryWriter 编码在文件中,它首先写入字符串长度。这样 BinaryReader 就知道在转换字符串之前要缓冲多少字节。

因此,在 ReadXxx() 方法之一返回并且在 BaseStream 上调用 Seek() 之后,缓冲区始终为空。这也是微软不需要重写 Seek() 方法的原因。

MSDN 文章中的警告说明是适当的,如果在 Seek() 调用之后调用 ReadXxx() 方法,您肯定多次阅读该“偏移”值。然而,我认为这完全是故意的。

于 2013-10-02T12:54:13.807 回答
4

我会说它并不总是安全的(尽管在某些情况下它可能是安全的)。

BinaryReader.BaseStream 的 Microsoft 文档明确指出:

在读取或使用 BinaryReader 时使用底层流可能会导致数据丢失和损坏。例如,可能会多次读取相同的字节,可能会跳过字节,或者字符读取可能变得不可预测。

所以我会避免它。

(有趣的是,有一种BinaryWriter.Seek()方法,但没有BinaryReader.Seek()。)

于 2013-10-02T09:57:13.380 回答
3

根据我的经验,只要您同时使用它们并且没有其他线程对流执行任何操作,那么它就可以正常工作。

我在我编写的使用二进制文件格式的应用程序中广泛这样做,并且从未遇到过问题。

于 2013-10-02T10:35:23.693 回答