[轉]C++流緩衝區的應用——輸出文件內容的方法舉例




   本文主要簡單討論C++流對象的底層緩衝區,並舉例介紹如何使用該緩衝區進行文件內容的輸出。如果文中有錯誤或遺漏之處,敬請指出,謝謝!
 
   作者: tyc611, 2007-01-23

簡要介紹
 
   C++標準庫封裝了一個緩衝區類streambuf,以供輸入輸出流對象使用。每個標準C++輸出輸出流對象都包含一個指向streambuf的指針,用戶可以通過調用rdbuf()成員函數獲得該指針,從而直接訪問底層streambuf對象。因此,可以直接對底層緩衝區進行數據讀寫,從而跳過上層的格式化輸入輸出操作。
 
   對於文件流類和字符串流類,分別派生了相應的流緩衝區類型,如下圖所示:
 
   流對象通過調用rdbuf()獲得了底層streambuf對象的指針,也就可以通過該指針調用streambuf支持你各種操作進行輸入輸出。本文對這些操作不予討論,在這裏主要介紹如何利用該指針實現文件內容的輸出。
 
   輸出流提供了一個重載版本operator<<,它以streambuf指針爲參數,實現把streambuf對象中的所有字符輸出到輸出流出中;輸入流也提供了一個對應的operator>>重載版本,把輸入流對象中的所有字符輸入到streambuf對象中。輸入流的get成員重載版本中還有以streambuf指針爲參數的版本,也可以用來把輸入流的東西寫入到輸出流緩衝區中。
 
   相關函數原型如下:
      basic_streambuf<E, T>* basic_ios<E, T>::rdbuf() const;
      basic_ostream<E, T>& basic_ostream<E, T>::operator<<(basic_streambuf<E, T> *sb);
      basic_istream<E, T>& basic_istream<E, T>::operator>>(basic_streambuf<E, T> *sb);
      basic_istream<E, T>& basic_istream<E, T>::get(basic_streambuf<E, T> *sb);
      basic_istream<E, T>& basic_istream<E, T>::get(basic_streambuf<E, T> *sb, E delim);

 

應用舉例
 
   下面用三種方法實現把一個文件的內容輸出標準輸出(當然還可以通過普通的標準格式化輸入輸出完成):
 
法一:通過operator<<
 

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream fin("source.dat");
    cout<<fin.rdbuf();
    
return 0;
}

法二:利用get成員函數

ifstream fin("source.dat");
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<<in.rdbuf()的地方換成in>>out.rdbuf(),代碼的功能完全一樣,效果也一樣。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章