標籤:輸入輸出 檔案流 get 自訂 fail -- 標準 code 派生
C++標準庫封裝了一個緩衝區類streambuf,以供輸入輸出資料流對象使用。每個標準C++輸出輸出資料流對象都包含一個指向streambuf的指標,用 戶可以通過調用rdbuf()成員函數獲得該指標,從而直接存取底層streambuf對象。因此,可以直接對底層緩衝區進行資料讀寫,從而跳過上層的格 式化輸入輸出操作。
對於檔案流類和字串流類,分別派生了相應的流緩衝區類型,參考最後面的代碼:
流對象通過調用rdbuf()獲得了底層streambuf對象的指標,也就可以通過該指標調用streambuf支援你各種操作進行輸入輸出。本文對這些操作不予討論,在這裡主要介紹如何利用該指標實現檔案內容的輸出。
輸出資料流提供了一個重載版本operator<<,它以streambuf指標為參數,實現把streambuf對象中的所有字元輸出到輸出資料流 出中;輸入資料流也提供了一個對應的operator>>重載版本,把輸入資料流對象中的所有字元輸入到streambuf對象中。輸入資料流的get成 員重載版本中還有以streambuf指標為參數的版本,也可以用來把輸入資料流的東西寫入到輸出資料流緩衝區中。
下面用三種方法實現把一個檔案的內容輸出標準輸出(當然還可以通過普通的標準格式化輸入輸出完成):
法一:通過operator<<
#include <iostream> #include <fstream> using namespace std; int main() { ifstream fin("source.dat"); cout<<fin.rdbuf(); //猜測實際上緩衝的資料載體就是一個char*,然後重載了<<運算子return 0; }
法二:利用get成員函數
ifstream fin("source.dat"); //get裡邊傳入什麼參數,就把流的內容輸入到什麼裡邊,這是輸入資料流的基本概念while (!fin.get(*cout.rdbuf()).eof()) { // extract a line input if (fin.fail()) // blank line fin.clear(); cout<<char(fin.get()); // extract ‘\n‘ }
代碼解釋:由於上面代碼中的get版本在遇到‘\n‘字元時,結束提取,所以需要用迴圈實現整個檔案內容的輸出。另外,當此版本get函數遇到空行 時,因為沒有提取到任何字元(注意:get不提取斷行符號符),注意會設定失敗標誌ios::failbit,所以此時應當調用clear()函數清除錯誤標 志。同樣,因為該版本get不會提取斷行符號符,所以需要用另一版本的get()提取斷行符號符。
法三:利用重載的get函數
ifstream fin("main.cpp"); fin.get(*cout.rdbuf(), EOF);
代碼解釋:這個版本的get成員函數可以自訂提取終止符。這裡通過設定為檔案結束符(EOF)來達到一下提取整個檔案的目的。
當然,你可以把上面的cout換成任意的輸出資料流,比如檔案輸出資料流,從而可以實現檔案的拷貝功能。
另外,上面代碼中並沒有使用輸入資料流的>>操作符,因為>>和<<是相對的,只是把運算元交換一下位置罷了。因此,你 可以把上面代碼中用out<<
[轉]c++流緩衝---rdbuf()