2013-10-02 29 views
5

由於BinaryReader的底層緩衝策略,我不清楚是否可以讀取存儲在流中的偏移量,然後在此偏移量處重新定位流以恢復流。BinaryReader打開時使用Stream.Seek是否安全?

作爲一個例子,是下面的代碼確定:

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 
} 

回答

9

BinaryReader的確使用緩衝區,但只有從基礎流中讀取足夠的字節來轉換值。換句話說,ReadInt32()將首先緩衝4個字節,ReadDecimal()將首先緩衝16個字節,等等。 ReadString()是一個比較棘手的方法,但它也有對策,一個字符串由BinaryWriter在文件中編碼,它首先寫入字符串長度。因此,BinaryReader在轉換字符串之前確切知道要緩衝多少個字節。

因此,在ReadXxx()方法返回並且在BaseStream上調用Seek()之後緩衝區總是空的。也是微軟不需要重寫Seek()方法的原因。

MSDN文章中的警告提示是適當的,如果您在Seek()調用後調用ReadXxx()方法,您當然會讀取多次「偏移」值。然而,我認爲這完全是故意的。

+2

Hans,如果在Seek()調用之後調用ReadXxx()方法,您爲什麼會多次讀取偏移值? BinaryReader不會只是重新填充緩衝區並給你正確的值?當然,除非偏移的值等於寫入的偏移本身的位置,否則你會剛剛回到開始的位置。 – BKewl

2

我會說這是總是安全(儘管它可能在某些情況下是安全的)。

The Microsoft documentation for BinaryReader.BaseStream明確規定:

使用底層流讀取或同時使用BinaryReader在可能導致數據丟失和損壞。例如,相同的字節可能會被讀取多次,字節可能會被跳過,或者字符讀取可能變得不可預測。

所以我會避免它。

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

2

以我的經驗,只要您同步使用他們兩個並沒有其他線程正在做與流什麼,然後它工作完美的罰款。

我在編寫用於處理二進制文件格式的應用程序中進行了廣泛的操作,並且從未遇到過問題。

相關問題