2013-07-08 25 views
11

Mam plik, który zawiera już pewne dane (na przykład 8 kB). Chcę przeczytać coś od początku pliku, a następnie nadpisać dane od miejsca, w którym skończyłem czytać. Więc staram się użyć następującego kodu:Odczytywanie i zapisywanie do tego samego pliku przy użyciu tego samego pliku fstream

std::fstream stream("filename", std::ios::in | std::ios::out | std::ios::binary); 

char byte; 
stream.read(&byte, 1); 

// stream.seekp(1); 

int bytesCount = 4096; 

auto bytesVec = std::vector<char>(bytesCount, 'c'); 
char* bytes = bytesVec.data(); 

std::cout << stream.bad() << std::endl; 

stream.write(bytes, bytesCount); 

std::cout << stream.bad() << std::endl; 

Gdybym wykonanie tego kodu, pierwsze bad() powraca false, ale drugi zwraca true i nic faktycznie dostaje napisane.

Jeśli zmniejszę wartość parametru bytesCount do wartości mniejszej niż 4096 (prawdopodobnie wielkość bufora wewnętrznego), drugi bad() zwraca false, ale nadal nic nie zostanie zapisane.

Gdybym odkomentuj linię seekp(), pisanie rozpoczyna pracę: bad() powraca false i bajtów rzeczywiście dostać napisane.

Dlaczego konieczne jest tutaj seekp()? Dlaczego nie działa bez niego? Czy seekp() jest właściwą metodą?

Używam Visual Studio 2012 na Windows 7.

Odpowiedz

19

Ty spadają wolny od ograniczeń po zmieszaniu z operacji odczytu i zapisu na pliku otwartego w trybie aktualizacji że fstream biblioteka MS za dziedziczy z jego implementacja C <stdio.h>.

C Standard (cytuję C99, ale nie różni się w tym momencie od C89) na 7.19.5.3/6 stanach:

Gdy plik jest otwarty w trybie aktualizacji ("+ "jako drugi lub trzeci znak na powyższej liście wartości argumentów trybu), zarówno dane wejściowe, jak i wyjściowe mogą być wykonywane w strumieniu powiązanym z . Jednak po wyjściu nie następuje bezpośrednio wejście bez wywołania interweniującego do funkcji fflush lub do funkcji pozycjonowania pliku (fseek, fsetpos lub do tyłu), a po wejściu nie następuje bezpośrednio wyjście bez interwencji do funkcji pozycjonowania pliku, chyba że operacja wejścia napotka koniec- pliku-.

(mój nacisk).

Więc twoje stream.seekp(1) rozwiązanie, które przenosi się do C fseek, jest poprawne.

Biblioteka GNU C nie ma tego standardowego ograniczenia, więc Twój kod jako opublikowany działa zgodnie z oczekiwaniami, gdy jest zbudowany z GCC.

Biblioteka MS <fstream> jest zgodna ze standardem C++ dziedziczenia tego ograniczenia. fstream s są realizowane za pomocą basic_filebuf<charT,traits>. W rachunku standardowym (C++ 11) tego szablonu, w § 27.9.1.1/2, po prostu jest napisane:

Ograniczenia dotyczące czytania i pisania sekwencji kontrolowanych przez obiekt klasy basic_filebuf są takie same jak do odczytu i zapisu z plikami PLIKU biblioteki standardowej C.

+0

Czy jest to również udokumentowane dla strumieni C++? Czy też wdrożenie MS nie jest zgodne ze standardem w tym zakresie? – svick

+0

@svick Zobacz aktualizację. –

0

Możesz zajrzeć do wiązanej strumieni - http://www.cplusplus.com/reference/ios/ios/tie/

To sprawia, że ​​za każdym razem, gdy wejście wczytuje wyjście automatycznie zostanie oczyszczony, czyli myślę żądane zachowanie, mimo że wymaga osobnego wejścia i strumień wyjściowy

Powiązane problemy