-
C++語言不直接處理輸入輸出,而是通過一族定義在標準庫中的類型來處理IO
iostream
定義了用于讀寫流的基本類型fstream
定義了讀寫命名文件的類型sstream
定義了讀寫內存string
對象的類型
-
標準庫使得我們能夠忽略這些不同類型的流之間的差異,是通過繼承機制實現的
-
不能拷貝或者對IO對象賦值,因此也不能將形式參數或者返回類型設置為流類型,進行IO操作的函數通常是已引用方式傳遞和返回流,讀寫一個IO對象會改變其狀態,因此傳遞和返回的引用不能是
const
的strm::iostate 提供表達條件狀態的完整功能 strm::badbit 用來指出流已經崩潰 strm::failbit 用來指出一個IO操作失敗了 strm::eofbit 用來指出流到達了文件結束 strm::goodbit 用來指出流未處于錯誤狀態,此值保證為零 s.eof() 若流s的eofbit置位,返回true s.fail() s.bad() s.good() 若流s處于有效狀態,返回true s.clear() 所有條件狀態復位,將流的狀態設置為有效,返回void s.clear(flags) 根據給定的flags標志位將流s中對應條件狀態位復位 s.setstate(flags)同上 s.rdstate() 返回流s的當前條件狀態
auto old_state = cin.rdstate(); //記住cin的當前狀態 cin.clear() //使cin有效 process_input(cin); //使用cin cin.setstate(old_state); //將cin置為原有狀態 cin.clear(cin.rdstate & ~cin.failbit & ~cin.badbit); //復位failbit和badbit,保持eofbit不變
-
通過緩沖機制,操作系統可以將程序的多個輸出操作組合成單一的系統級寫操作。(原因在于設備的寫操作可能很耗時)
-
導致緩沖刷新的原因:
- 程序正常結束,作為
main
函數的return
操作的一部分,緩沖刷新被執行 - 緩沖區滿
- 使用操縱符
endl
顯式刷新緩沖區 - 在每個輸出操作后,可以用操作符
unitbuf
設置流的內部狀態,來清空緩沖區(默認情況下cerr
是設置unitbuf
的,因此寫到cerr
的內容都是立即刷新的) - 一個輸出流可能被關聯到另一個流。在這種情況下,當讀寫被關聯的流時,關聯到的流的緩沖區會被刷新
- 程序正常結束,作為
-
除了
endl
外,還可以使用flush
和ends
刷新緩沖區,但是他們有不同的效果:cout << "hi" << endl; //輸出"hi\n" cout << "hi" << flush; //輸出"hi" cout << "hi" << ends; //輸出"hi "
-
如果想在每次輸出操作后都刷新緩沖區,我們可以使用
unitbuf
操縱符,它告訴流在接下來每次寫操作后都進行一次flush
操作cout << unitbuf; //所有輸出操作都會立即刷新緩沖區 cout << nounitbuf; //回到正常的緩沖方式
-
調試/程序崩潰時要記得及時刷新緩沖區
-
當一個輸入流被關聯到一個輸出流時,任何試圖從輸入流讀取數據的操作都會先刷新關聯的輸出流(例如
cin
和cout
)。交互式系統通常應該關聯輸入流和輸出流。每個輸入流最多關聯到一個流,但多個流可以同時關聯到同一個ostream
cin.tie(); //返回cin關聯的流,如果之前沒有關聯則返回空指針 cin.tie(&cout); //返回值同上,但是將cin與cout關聯 ostream *old_tie = cin.tie(nullptr); //取消關聯,同時保存關聯的流的指針 cin.tie(old_tie); //恢復關聯
-
文件輸入輸出的流定義在頭文件
fstream
中fstream fstrm; fstream fstrm(s); 打開名為s的文件,s可以是string類型或者是一個指向C風格字符串的指針,默認的文件模式mode依賴 fstream的類型 fstream fstrm(s, mode); fstrm.open(s); 打開名為s的文件,并將文件與fstrm綁定,返回void fstrm.close(); 關閉與fstrm綁定的文件,返回void fstrm.is_open(s); 返回一個bool,指出與fstrm關聯的文件是否打開成功且尚未關閉
-
我們可以用
fstream
代替iostream&
,即在需要接受一個iostream
類型引用或者指針參數的函數可以用一個對應的fstream
或sstream
來調用 -
在使用流之前檢查是一個好的習慣
-
當一個
fstream
對象被銷毀時,close
會自動被調用 -
每個流都有一個關聯的文件模式,用來指出如何使用文件
in 以讀方式打開,只可以對ifstream或fstream out 以寫方式打開,只可以對ofstream或fstream,默認情況下,即使我們沒有指定trunc,以out模式打開的文件也會被截 斷,為了保留以out模式打開的文件的內容,我們必須同時指定app,或者指定infstream默認關聯in和out app 每次操作均定位到文件末尾,只要trunc沒有被設定就可以設定,包含out ate 打開文件后立即定位到文件末尾 trunc 截斷文件,只有當out也被設定時才能設定 binary 以二進制方式進行IO
//下面三種方式打開文件是等價的,都會截斷文件 ofstream out("file"); ofstream out("file", ofstream::out); ofstream out("file", ofstream::out | ofstream::trunc); //為了保留文件的內容,我們必須顯式指定app模式 ofstream out("file", ofstream::app); ofstream out("file", ofstream::out | ofstream::app);
-
sstream
頭文件定義了三個類型來支持內存IO,這些類型可以向string
寫入數據,從string
讀取數據 -
istringstream
從string
讀取數據,ostringstream
向string
寫入數據,stringstream
既可以讀也可以寫sstream strm; sstream strm(s); strm保存string類型的s的拷貝 strm.str() 返回strm保存的string的拷貝 strm.str(s) 將string s拷貝到strm中,返回void