C++系統學習之八:IO庫

  新的C++標準中有三分之二的內容都是描述標準庫。接下來重點學習其中幾種核心庫設施,這些是應該熟練掌握的。

  標準庫的核心是很多容器類(順序容器和關聯容器等)和一簇泛型算法(該類算法通常在順序容器一定範圍內的元素上或其他類型的序列上進行操作)。

  該篇主要學習IO庫。

  C++語言不直接處理輸入輸出,而是通過一簇標準庫中的IO庫來處理。IO庫定義了讀寫內置類型值的操作。

1、IO類

  爲了處理不同的種類的IO操作,定義了:iostream(用於讀寫流的基本類型)、fstream(讀寫命名文件的類型)、sstream(讀寫內存string對象的類型)。

其中後面以w開頭的是寬字符版本。

IO類型間的關係

繼承機制:ifstream和istringstream都是繼承自istream,上述所有的IO庫類型之間都存在這種繼承關係。

下面介紹的標準庫流特性都可以無差別地應用於普通流、文件流和string流,以及它們的寬字符版本。

1.1 IO對象無拷貝或賦值

不能拷貝或對IO對象賦值

ofstream out1,out2;
out1=out2;    //錯誤,不能對流對象賦值
ofstream print(ofstream);    //錯誤,不能初始化ofstream參數
out2=print(out2);        //錯誤,不能拷貝流對象

因爲不能拷貝IO對象,因此不能將形參或返回類型設置爲流類型。進行IO操作的函數通常以引用方式傳遞和返回流。讀寫一個IO對象會改變其狀態,因此傳遞和返回的引用不能是const。

1.2 條件狀態

IO操作可能會發生錯誤,IO類通過定義一些條件狀態來顯示IO對象的狀態,使用戶知道流的當前狀態。

由於流操作可能發生的錯誤,因此,代碼通常應該在使用一個流之前檢查它是否處於良好狀態,最簡單的方法是將它當作一個條件來使用。

while(cin>>word)
{
    ......
}

查詢流的狀態

有時候不僅僅需要知道流是否有效,還要知道到底是什麼原因導致流失效,IO庫定義了一個與機器無關的iostate類型,它提供了表達流狀態的完整功能。這個類型應作爲一個位集合來使用。

使用good或fail是確定流的總體狀態的正確方法。上述將流作爲條件使用的代碼等價於!fail()。

 

while(cin>>word)
{
    ......
}

==================

cin >> s;
while (!(cin.fail()))
{

}

 管理條件狀態

流對象的rdstate成員返回一個iostate值,對應流的當前狀態。setstate操作將給定條件位置位,表示發生了對應錯誤。clear成員是一個重載的成員。有一個無參數的版本,清除所有錯誤標誌位。

auto old_state=cin.rdstate();    //記住cin的當前狀態
cin.clear();    //清除所有錯誤
process_input(cin);    //使用cin
cin.setstate(old_state);    //將cin置爲原有狀態

 1.3 管理輸出緩衝

每個輸出流都管理一個緩衝區,用來保存程序讀寫的數據。

 刷新輸出緩衝區

已經使用過操縱符endl,它完成換行並刷新緩衝區的工作。IO庫還有兩個類似的操縱符:flush和ends。flush刷新緩衝區,但不輸出任何額外的字符;ends向緩衝區插入一個空字符,然後刷新緩衝區。

unitbuf操縱符

unitbuf每次輸出操作後都刷新緩衝區。它告訴流在接下來的每次寫操作之後都進行一次flush。而nounitbuf操縱符則重置流,使其恢復正常的系統管理的緩衝區刷新機制。

cout<<unitbuf;    //所有輸出操作後都會立即刷新緩衝區

cout<<nounitbuf;    //回到正常的緩衝方式

2、文件輸入輸出

 頭文件fstream定義了三種類型來支持文件IO:ifstream、ofstream、fstream。

fstream除了繼承自iostream類型的行爲之外,fstream還定義了一些自己專有的操作。這是其他IO類型所沒有的。

2.1 使用文件流對象

用fstream代替iostream&

在使用iostream的地方,可以用fstream代替調用,因爲fstream是從iostream繼承來的。

成員函數open和close

可以先定義一個空文件流對象,然後用open將其與文件關聯起來。

如果調用open失敗,則failbit會被置位,因此進行open是否成功的檢測是一個好的習慣。

ofstream out;
out.open("1.txt");
if(out)
.......

將文件流對象綁定到另一個文件之前,需要先close已經關聯的文件,然後再關聯新的文件。

自動構造和析構

當一個fstream對象被銷燬時,close會自動被調用。

2.2 文件模式

每個流都有一個關聯的文件模式,用來指出如何使用文件。

指定文件模式有如下限制

  • 只可以對ofstream和fstream對象設定out模式
  • 只可以對ifstream和fstream對象設定in模式
  • 只有當out也被設定時纔可設定trunc模式
  • 只要trunc沒被設定,就可以設定app模式。在app模式下,即使沒有顯式指定out模式,文件也總是以輸出方式被打開
  • ate和binary模式可用於任何類型的文件流對象,且可以與其他任何文件模式組合使用

每個文件流類型都定義了一個默認的文件模式,ifstream是in,ofstream是out,fstream是in和out

以out模式打開文件會丟棄已有數據

默認情況下,打開一個ofstream時,文件的內容會被丟棄。阻止一個ofstream清空給定文件內容的方法是同時指定app模式。

ofstream app("file",ofstream::app);    
ofstream app2("file",ofstream::out | ofstream::app); 

 每次調用open時都會確定文件模式

ofstream out;
out.open("file1");    //模式隱含設置爲輸出和截斷
out.close();
out.open("file2",ofstream::app);   //模式爲輸出和追加
out.close();    

 通常情況下,out模式意味着同時使用trunc模式,因此,file1的文件的內動將被清空。

每次打開文件時,都要設置文件模式,可能是顯式地設置,也可能是隱式地設置,當程序未指定模式時,就使用默認值。

3、string流

 sstream頭文件定義了三個類型來支持內存IO,這些類型可以向string讀寫數據,string像是一個IO流一樣。

  • istringstream
  • ostringstream
  • stringstream

上述三種都繼承自iostream。同樣的,除了繼承來的操作,其也定義了自己特有的操作。

 

 

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