当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()
。)