2013-07-08 29 views
11

我有一個已經包含一些數據(比如,8 KB)的文件寫入到同一個文件。我想從文件的開頭讀取一些內容,然後在我讀完的地方重寫數據。所以,我嘗試使用下面的代碼:閱讀和使用相同的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; 

如果我執行這個代碼,第一bad()回報false,但第二個返回true和實際並沒有任何書面。

如果我將bytesCount減小到小於4096的任何值(大概是某個內部緩衝區的大小),第二個bad()返回false,但仍然沒有寫入任何內容。

如果我取消對seekp()行的註釋,則寫入開始工作:bad()返回false並且實際寫入的字節。

爲什麼這裏的必要seekp()?爲什麼沒有它,它不工作? seekp()是否是正確的方法?

我使用Visual Studio 2012在Windows 7

回答

19

你這是在讀取和 寫操作的混合在更新模式打開的文件MS的fstream 庫從繼承落下限制的犯規它的C <stdio.h>執行。

C標準(我舉C99,但它不會從C89這點不同)在7.19.5.3/6狀態 :

當一個文件被打開與更新模式('+ '如在 上述模式的參數值的列表中的第二或第三個字符),輸入和輸出可在 相關流進行。然而,輸出不應直接跟隨輸入,而不需要中間呼叫到fflush功能或文件定位功能(fseek, fsetpos或後退),並且輸入不應直接跟隨輸出,而不要輸入中間呼叫 到文件中的定位功能,除非輸入操作遇到最終的文件 。

(我的重點)。

所以你stream.seekp(1)的解決方案,其中,轉予一個C fseek,是正確的。

GNU C庫沒有此標準限制,因此張貼您的代碼工作 按預期與海灣合作委員會建立。

MS <fstream>庫在繼承 此限制時符合C++標準。 fstream使用basic_filebuf<charT,traits>來實現。在(C++ 11)標準的戶口本模板,在§27.9.1.1/2,它只是說:

上閱讀的限制,並通過編寫類basic_filebuf的目標控制的順序是一樣的至於使用標準C庫FILE進行讀寫。

+0

這是爲C++流記錄嗎?或者MS的實施不遵循這方面的標準? – svick

+0

@svick查看更新。 –