2013-10-02 19 views
5

Z powodu strategii buforowania pod maską BinaryReadera, nie jest dla mnie jasne, czy jest w porządku, czy nie czytać offsetu zapisanego w strumieniu, a następnie zmienić położenie strumienia w tym przesunięciu, aby wznowić przesyłanie strumieniowe.Czy można bezpiecznie używać Stream.Seek, gdy BinaryReader jest otwarty?

Jako przykład jest kod dodaje ok:

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

    //Then resume reading the streaming 
} 

Albo powinienem zamknąć pierwszy czytnik binarnego przed Poszukiwany strumienia, a następnie ponowne otwarcie drugiego czytnika?

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 
} 

Odpowiedz

9

BinaryReader używa bufora, ale tylko, aby odczytać wystarczającą liczbę bajtów ze strumienia bazowego, aby przekonwertować wartość. Innymi słowy, ReadInt32() będzie najpierw buforował 4 bajty, ReadDecimal() będzie buforował po 16 bajtów, etcetera. ReadString() jest trudniejszą metodą, ale ma również środki zaradcze, łańcuch jest zakodowany w pliku przez BinaryWriter, który najpierw zapisuje długość łańcucha. Tak więc BinaryReader dokładnie wie, ile bajtów buforować przed konwersją ciągu.

Tak więc bufor jest zawsze pusty po powrocie do metody ReadXxx() i wywołanie funkcji Seek() w BaseStream jest w porządku. Również powód, dla którego Microsoft nie musiał przesłonić metody Seek().

Uwaga ostrzegawcza w artykule MSDN jest właściwa, z pewnością będzie odczytać tę wartość "offset" więcej niż raz, jeśli wywołasz metodę ReadXxx() po wywołaniu Seek(). Zakładam jednak, że było to całkowicie zamierzone.

+2

Hans, dlaczego odczytałeś wartość offsetu więcej niż raz, jeśli wywołasz metodę ReadXxx() po wywołaniu Seek()? Czy BinaryReader po prostu nie napełni bufora i nie poda poprawnych wartości? O ile, oczywiście, przesunięcie nie ma wartości równej położeniu samego zapisanego przesunięcia - wtedy skończysz z miejsca, z którego zacząłeś. – BKewl

2

Powiedziałbym, że jest nie zawsze bezpieczny (choć może to być bezpieczne w niektórych przypadkach).

The Microsoft documentation for BinaryReader.BaseStream wyraźnie stwierdza:

Korzystanie z podstawowej strumienia podczas czytania lub podczas korzystania z BinaryReader może spowodować utratę danych i korupcji. Na przykład te same bajty mogą być czytane więcej niż raz, bajty mogą być pomijane lub czytanie znaków może stać się nieprzewidywalne.

Więc chciałbym tego uniknąć.

(Co ciekawe, istnieje BinaryWriter.Seek() metoda, ale nie BinaryReader.Seek().)

2

z mojego doświadczenia tak długo jak używasz ich obu synchronicznie i żaden inny wątek nie robi nic ze strumienia to działa perfekcyjnie.

Robię to szeroko w aplikacjach napisanych do pracy z formatami plików binarnych i nigdy nie napotkałem problemu.