当BinaryReader打开时使用Stream.Seek是否安全?

由于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 } 

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

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

MSDN文章中的注意事项是合适的,如果在Seek()调用之后调用ReadXxx()方法,您肯定多次读取“offset”值。 但我认为这完全是故意的。

根据我的经验,只要你同时使用它们,没有其他线程正在对流做任何事情,那么它的工作完全正常。

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

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

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

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

所以我会避免它。

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