c++ 語言中不直接處理輸入和輸出,而是通過一族定義在标準庫中的類型來處理IO,這些類型支援從裝置讀取資料、向裝置寫入資料的IO操作。裝置可以是檔案、控制台視窗等。還有一些IO運作記憶體IO,即可以從string中讀寫資料。
IO庫
IO類
最開始接觸的c++ 中的io是我們從控制台接受輸入的istream和輸出到控制台中的ostream。除了基本的istream和ostream以外标準庫中還定義了如下的基本類型
iostream 用于讀寫流的基本類型
- istream、wistream: 從流讀取資料
- ostream、wostream: 向流寫入資料
- iostream、wiostream:從流中讀寫資料
fstream 定義了讀寫命名檔案的類型
- ifstream、wifstream: 從檔案中讀寫資料
- ofstream、wofstream: 向檔案中寫入資料
- fstream、wfstream: 讀寫檔案
sstream 定義了讀寫記憶體string對象的類型
- istringstream、iwstringstream: 從string中讀取資料
- ostringstream、owstringstream: 向string中寫入資料
- stringstream、wstringstream: 讀寫string
其中帶w的都是款位元組版本
無法對io對象進行拷貝或者指派、是以在函數中無法傳回IO類型也無法傳遞IO類型,隻能使用IO類型的引用
讀寫一個IO對象會改變其狀态,是以在函數中傳遞和傳回IO的對象不能是const的
一個流如果發生錯誤,其上後續的IO操作都會失敗。隻有當一個IO流處于無錯誤狀态時,我們才能從它讀取資料。是以代碼通常應該在使用一個流之前檢查它是否處于良好狀态,确定一個流對象的狀态最簡單的方式是将它作為一個條件來使用。
作為條件使用隻能告訴我們流是否有效,而無法告訴我們具體發生了什麼。IO庫定義了一組與機器無關的iostate類型,這個類型中使用二進制位來表示每種狀态。目前定義了4種錯誤類型:
- badbit: 流崩潰
- failbit: IO操作失敗
- eofbit: 流到達了檔案結束位置
- goodbit: 流未處于錯誤狀态
在實際使用時可以将具體值與這些預定義的值做位與運算,得到具體的原因
流對象的rstate 成員傳回目前流的狀态,setstate用來設定流狀态。clear不帶參用來清理所有錯誤标志位。clear的帶參版本接受一個iostate值,表示流的新狀态
io操作比較耗時,是以作業系統為了效率會提供緩沖機制。輸入輸出并不是立即執行的,作業系統提供了一個緩沖區,在适當的實際會使用緩沖區的資料,統一執行輸入輸出操作。導緻重新整理的原因有很多:
- 程式正常結束,在main函數執行return時,會進行重新整理操作
- 緩沖區滿時,會進行換新操作
- 程式中使用操作符例如endl來顯式的重新整理緩沖區
- 輸出操作結束後,使用操作符unitbuf 設定流的内部狀态來清空緩沖區,預設情況下cerr 是設定了unitbuf 的,是以cerr的内容都是實時重新整理的
- 一個輸出流被關聯到另一個輸出流。當讀寫被關聯到另一個流時,關聯到的流的緩沖區會被重新整理
除了使用endl、flush、ends 都可以來重新整理緩沖區。endl在重新整理的同時會插入換行符,flush則不添加任何字元,ends會添加一個空字元
如果想在每次輸出後都重新整理緩沖區,可以使用unitbuf 操作符,它告訴流,每次執行寫操作之後都進行一個flush操作
cout << unitbuf;
cout << nounitbuf;
如果程式崩潰,緩沖區是不會被重新整理的
标準庫是将cin和cout關聯到一起了,是以每次執行cin都會導緻cout的緩沖區被重新整理
可以使用tie 方法将自身關聯到另一個流上。
tie 帶參數的版本,需要傳入一個指向ostream 的指針,将自己關聯到這個ostream中
tie 不帶參數的版本用來查詢自身關聯到了哪個輸出流上,傳回對應輸出流的指針,如果未被關聯,則傳回空指針
每個輸入流最多隻能關聯到一個輸出流,但是多個輸入流可以關聯到同一個ostream
檔案IO
當我們要讀寫一個檔案時可以使用檔案流對象
ifstream in(ifile); //傳入檔案名,構造一個ifstream 并打開檔案
ofstream out; //定義一個檔案輸出流,這個流不關聯到任何檔案
當我們定義了空的檔案流對象後可以使用open函數将對象和檔案關聯起來。可以手動調用close函數關閉檔案。也可以在fstream對象被銷毀時由它的構造函數自動調用close
每個流都有一個關聯的檔案模式,用來指出該如何使用檔案
- in: 以讀的方式打開
- out: 以寫的方式打開
- app: 每次寫操作前均定位到檔案尾部
- ate: 每次打開檔案後立即定位到檔案尾部
- trunc: 截斷檔案
- binary:以二進制的形式打開檔案