IO庫

1 C++緩沖區(qū)

在學習標準IO庫之前,我們先了解C++中緩沖區(qū)的使用。關(guān)于操作系統(tǒng)中緩沖區(qū)的學習與理解,請查看操作系統(tǒng)-緩存管理。

1.1 什么是緩沖區(qū)

緩沖區(qū)又稱緩存,是內(nèi)存空間的一部分。系統(tǒng)在內(nèi)存中預(yù)留一部分用于緩沖輸入輸出的數(shù)據(jù),緩沖區(qū)根據(jù)用途分為輸入緩沖區(qū)輸出緩沖區(qū)兩種。

1.2 為什么要引入緩沖區(qū)

C++中緩沖區(qū)的使用主要有以下幾個目的:

  • 緩和CPU與I/O設(shè)備間速度不匹配的矛盾。
  • 減少對CPU的中斷頻率,放寬對CPU中斷響應(yīng)時間的限制。
  • 提高CPU和I/O設(shè)備之間的并行性,讓CPU可以處理其他工作
1.3 緩沖區(qū)類型

C++緩沖區(qū)分為全緩沖、行緩沖和無緩沖三種。

  • 全緩沖
    在此類緩沖中,當填滿標準I/O緩沖后,才進行實際的I/O操作。典型的代表是磁盤文件的讀寫。

  • 行緩沖
    在此類緩沖中,當在輸入和輸出中遇到換行符時,執(zhí)行真正的I/O操作。輸入的字符先存放在緩沖區(qū),等按下回車鍵換行時才進行實際的I/O操作。典型代表是鍵盤輸入數(shù)據(jù)。

  • 無緩沖
    標準出錯情況stderr是典型代表,這使得出錯信息可以直接盡快地顯示出來。

1.4 緩沖區(qū)的刷新

下列情況將導(dǎo)致緩沖區(qū)刷新

  • 程序正常結(jié)束
    作為main函數(shù)return的一部分,緩沖刷新被執(zhí)行。

  • 緩沖區(qū)滿
    需要刷新緩沖,新數(shù)據(jù)才可寫入。

  • 使用操作符控制緩沖區(qū)刷新
    endl:輸出內(nèi)容加換行,然后刷新
    ends:輸出內(nèi)容加空字符,然后刷新
    flush:輸出內(nèi)容后直接刷新

  • unitbuf設(shè)置流的內(nèi)部狀態(tài)

cout << unitbuf; //所有輸出操作后會立即刷新緩沖區(qū)
cout << <<nounitbuf; //回到正常的緩沖方式
  • 一個輸出流被關(guān)聯(lián)到另一個流上
    使用tie函數(shù)可以將兩個流關(guān)聯(lián)在一起。當讀寫被關(guān)聯(lián)的流,被關(guān)聯(lián)的流會刷新。cincerr都關(guān)聯(lián)到cout,因此讀cin或者cerr都會導(dǎo)致cout的緩沖區(qū)更新。我們可以將istream關(guān)聯(lián)到ostream上,也可將ostream關(guān)聯(lián)到另一個ostream上。不建議將cin關(guān)聯(lián)到cerr上。

警告:如果程序崩潰了,則不會刷新緩沖區(qū)。

1.5 行緩沖演示

getchar()是行緩沖的,第一次調(diào)用getchar()函數(shù),會讓程序使用者輸入一行字符并直至按下回車鍵函數(shù)才返回。此時用戶輸入的字符和回車符都存放在行緩沖區(qū)。再次調(diào)用getchar()函數(shù),會逐步輸出行緩沖區(qū)的內(nèi)容。

int main(){
    char c;
    c = getchar();
    cout << c << endl;
    while ((c = getchar())!= '\n'){
        cout << c << endl;
    }
}
/*一次性輸入 a b c
輸出
a
b
c
*/

2 IO類

iostream中的類型和對象都是操作char數(shù)據(jù)的。默認情況下,這些對象都是關(guān)聯(lián)到用戶控制臺的窗口的。

為了支持不同種類的IO處理操作,在istreamostream之外,標準庫還定義了一些其他的IO類型。iostream定義了用于讀寫流的基本類型,fstream定義了讀寫命名文件的類型,sstream定義了讀寫內(nèi)存string對象的類型。

為了支持寬字符的語言,標準庫定義了一組類型和對象來操作wchar_t類型的數(shù)據(jù)。寬字符版本的類型和函數(shù)的名字以一個w開始,與其普通char版本定義在同一個頭文件中。

2.1 IO對象無拷貝

由于不能拷貝IO對象,因此我們不能將形參或返回類型設(shè)置為流類型。進行IO的函數(shù)通常以引用方式傳遞和返回流。讀寫一個IO對象會改變其狀態(tài),因此傳遞和返回的引用不能是const。

2.2 條件狀態(tài)

IO類所定義的一些函數(shù)和與機器無關(guān)的iostate標志,可以幫助我們訪問和操作流的條件狀態(tài)。

1) 條件狀態(tài)說明

上述任何一個IO對象在任意時刻都有一種狀態(tài),iostate代表狀態(tài)的枚舉,badbit,failbit,eofbit,goodbitiostate的一個具體值。

操作good在所有錯誤位均未置位的情況下返回true。而badbitfailbiteofbit任一被置位,檢測流的狀態(tài)條件會失敗,此時fail操作返回true。badfaileof只有在相應(yīng)錯誤為被置位時才返回true。

一個流一旦發(fā)生錯誤,其上后續(xù)的IO操作都會失敗。只有當一個流處于無錯狀態(tài)時,我們才可對它讀寫數(shù)據(jù)。通常用以下語句檢查一個流在使用前的狀態(tài):

while (cin >> word)
    //輸入操作成功,流保持有效,條件狀態(tài)為真

** 2) 條件狀態(tài)管理**

流對象的rdstate成員返回一個iostate值,對應(yīng)流的當前狀態(tài)。setstate操作將給定條件為置位,表示發(fā)生了對應(yīng)錯誤。

clear成員是一個重載函數(shù),提供兩個版本:clear無參數(shù)版本將復(fù)位所有錯誤標志位,帶參數(shù)版本提供一個新的iostate狀態(tài)。

2.3 管理輸出緩沖

關(guān)于緩沖區(qū)內(nèi)容本章開頭有介紹。

3 文件輸入輸出

ifstream從一個給定的文件讀取數(shù)據(jù),ofstream向一個給定文件寫入數(shù)據(jù),fstream可以讀寫給定文件。

可以用getline函數(shù)從一個ifstream讀取數(shù)據(jù),除繼承自iostream類型中行為外,fsteam還提供了一下成員來管理與流關(guān)聯(lián)的文件。

3.1 使用文件流

當需要讀寫一個文件時,可以定義一個文件流對象,并將對象與文件關(guān)聯(lián)起來。文件名可以用string類型,也可以用傳統(tǒng)C風格字符串。

1) 成員函數(shù)open和close

如果我們定義了一個空文件流對象,可以隨后用open將它與文件關(guān)聯(lián)起來。如果調(diào)用open失敗。failbit將會被置位。因此檢測open是否成功是一個好習慣。

使用close函數(shù)可關(guān)閉文件流所綁定的文件。

string text;
ifstream fstm;
fstm.open("test.txt");
if (fstm){
    getline(fstm, text);
    cout << text;
    fstm.close();
}
else{
    cout << "failed";
}
\\如果順利打開test.txt,條件為真,則從中讀取內(nèi)容,輸出并關(guān)閉文件
\\打開失敗則輸出failed

2) 自動構(gòu)造和析構(gòu)

當一個fstream離開其作用域,close會自動被調(diào)用,與之關(guān)聯(lián)的文件會自動關(guān)閉。

3.2 文件模式

在打開文件時,無論是調(diào)用 open還是以文件名作為流初始化的一部分,都需指定文件模式(file mode)。

  • 只可以對ofstreamfstream對象設(shè)定out模式

  • 只可以對ifstreamfstream對象設(shè)定in模式

  • 只有打開out模式,才可設(shè)定trunc模式

  • 只要trunc模式未被設(shè)定,就可設(shè)定app模式。在app模式下,即使沒有顯示指定out模式,文件也總以輸出模式被打開

  • 默認情況下,以out模式打開文件,在位指定trunc時,也將被截斷。為保留其中內(nèi)容,可以使用app模式或者in模式(文件同時讀寫)

  • atebinary模式可用于任何類型的文件流對象且可以與其他模式組合使用。ate 模式只在打開時有效:文件打開后將定位在文件尾。以 binary模式打開的流則將文件以字節(jié)序列的形式處理,而不解釋流中的字符。

默認情況下,當我們打開一個ofstream時,文件內(nèi)容會被丟棄。對于用 ofstream 打開的文件,要保存文件中存在的數(shù)據(jù),唯二方法是顯式地指定app模式或 in 模式打開:

4 string流

sstream頭文件中定義了以下三個類型來支持內(nèi)存IO。

istringstreamstring中讀取數(shù)據(jù),ostringstreamstring中寫入數(shù)據(jù),而stringstream即可從string讀數(shù)據(jù)也可以向string寫數(shù)據(jù)。出了從iostream中繼承的操作外,sstream中還支持以下操作:

4.1 sstream的使用
string line, word; 
while (getline(cin, line)) {
    istringstream stream(line);
    while (stream >> word){
        // do per-word processing
    }
}

string中數(shù)據(jù)全部讀出后,同樣會觸發(fā)“文件結(jié)束”信號,此時while循環(huán)條件為false。

4.2 轉(zhuǎn)換或格式化

sstream類似于C語言風格中ssprintf,可以方便地構(gòu)造各種風格的string。

string format_message = "cp 3 lbj 23";
istringstream input(format_message);
ostringstream output;

int val1 = 0, val2 = 0;
string str1, str2;

input >> str1 >> val1 >> str2 >> val2;
output << val1 << " " << val2 << endl; 
cout << output.str();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 版權(quán)聲明:本文為 cdeveloper 原創(chuàng)文章,可以隨意轉(zhuǎn)載,但必須在明確位置注明出處! 標準 IO 庫 上一篇...
    登龍zZ閱讀 699評論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • I/O 庫提供了兩套不同風格的文件處理接口。 第一種風格使用隱式的文件句柄; 它提供設(shè)置默認輸入文件及默認輸出文件...
    chiguozi閱讀 6,775評論 1 4
  • 開發(fā)工作中我們都需要選擇一個文本編輯器,從最開始的EditPlus 到nodepad++,還有UltraEdit ...
    一笑yo閱讀 299評論 0 2
  • 如果上市公司董秘技能水平都不及保薦代表人,或者獨立第三方服務(wù)機構(gòu)(律所、會計師事務(wù)所,評估機構(gòu)等),那么上市公司的...
    桃子torri閱讀 1,038評論 2 6

友情鏈接更多精彩內(nèi)容