淺談C++ IO流
1.輸入輸出(IO)與流的概念
輸入輸出(IO)是指計算機同任何外部設備之間的數據傳遞。常見的輸入輸出設備有文件、鍵盤、打印機、屏幕等。數據可以按記錄(或稱數據塊)的方式傳遞,也可以 流的方式傳遞。
所謂記錄,是指有著內部結構的數據塊。記錄內部除了有需要處理的實際數據之外,還可能包含附加信息,這些附加信息通常是對本記錄數據的描述。
流是一種抽象概念,它代表了數據的無結構化傳遞。按照流的方式進行輸入輸出,數據被當成無結構的字節(jié)序或字符序列。從流中取得數據的操作稱為提取操作,而向流中添加數據的操作稱為插入操作。用來進行輸入輸出操作的流就稱為IO流。換句話說,IO流就是以流的方式進行輸入輸出。
C++IO流,特指以流的方式進行輸入輸出的ISO/ANSI標準C++庫的輸入輸出類庫,也就是專門負責處理IO操作的一套系統(tǒng)。任何需要傳遞的數據,都要經過這套系統(tǒng)的處理。
2.數據的表示形式
IO操作的過程中,任何需要被傳遞的數據,在經過IO類庫處理前后是不同的。這樣,我們可以把數據的表示分為兩種:內部表示和外部表示。
數據的內部表示便于程序進行數據處理。典型的內部表示有:整型數的二進制表示、浮點數的IEEE表示、字符的ASCII或Unicode編碼表示。數據的外部表示則根據不同的外部設備的需要,有具體不同的表現形式。如果外部數據表示是可讀的字符序列,則稱為文本IO,否則為二進制IO。標準IO流的主要目的是支持文本IO,不直接支持二進制IO。
雖然IO流是以流的方式進行數據傳遞,但這并不表明傳遞的數據不能有任何結構,而是指IO流的概念是以流的方式進行輸入輸出,所傳遞數據的內部結構隱藏在對流數據的解釋中。
3.IO的步驟
在IO流里,輸入輸出分為4步:格式化/解析,緩沖,編碼轉換和傳遞。
格式化/解析:在內部數據表示(以字節(jié)為單位)與外部數據表示(以字符為單位)之間進行雙向轉換。例如一個2字節(jié)的整數10002,就需要5個字符來表示。
緩沖:用于在格式/解析與傳遞只加緩存字符序列。對于輸出,較短的字符序列格式化之后并不馬上輸出,而是保存在緩沖區(qū)里,待累積到一定規(guī)模之后再傳遞到外部設備。相反,從外部設備讀入的大量數據也是先放在緩沖區(qū),然后逐步取出完成輸入。默認時,IO流的輸入輸出都是經過緩沖的,也可以讓IO流工作在無緩沖模式下。
編碼轉換: 是將一種字符表達式轉換成另一種字符表達式。如果格式化產生的字符表達式與外部字符表達式不同(輸出時),或者外部表達式與IO流能解析的表達式不同(輸入時),就必須進行編碼轉換。如多字節(jié)編碼與寬字符編碼之間的轉換等。多數情況下并不需要進行編碼轉換。
傳遞:主要是與外部設備進行通信。輸出時,傳遞負責將經過格式化、緩沖即編碼轉換后的字符序列發(fā)送到外部設備;輸入時,則負責將外部設備抽取數據,為其后進行的編碼轉換、緩沖及解析提供字符序列。
4.IO流類庫的組成結構
IO流類庫在不同平臺的具體實現上,可能會有所變化,但從總體設計上來看,C++流庫主要由兩個流類層次組成:
(1)以streambuf類為父類的類層次
主要完成信息通過緩沖區(qū)的交換。派生層次如下:
緩沖區(qū):是一個隊列數據結構,由一字符序列和兩個指針組成,這兩個指針分別指向字符要被插入或被取出的位置。
streambuf類為所有的streambuf類層次對象設置了一個固定的內存緩沖區(qū),動態(tài)劃分為兩部分:
用做輸入的取區(qū),用取指針指示當前取字符位置。
用做輸出的存區(qū),用存指針指示當前存字符位置。
(2)以ios類為父類的類層次
ios類及其派生類是在streambuf類實現的通過緩沖區(qū)的信息交換的基礎上,進一步增加了各種格式化的輸入/輸出控制方法。它們?yōu)橛脩籼峁┦褂昧黝惖慕涌?,它們均有一個指向streambuf的指針。
ios類有四個直接派生類:
- istream
- ostream
- fstreambase
- strstreambase
這四種流作為流庫中的基本流類。ios類的派生層次如下:
5. IO流類庫的優(yōu)點
C++語言開發(fā)了自己的IO流類庫,用以取代C語言的基本輸入輸出函數族。對于有經驗的C程序員來說,C語言提供的IO函數庫時有效且方便的。但是,C語言的IO函數庫有其自身的缺點,特別是在C++這種面向對象的程序設計語言中,C語言函數庫無法直接支持面向對象的程序設計。因此,C++語言開發(fā)自己的IO流類庫是必然的。具體來說,IO流類庫具有以下優(yōu)點。
(1)簡明與可讀性
IO流類庫用IO運算符(提取運算符>>和插入運算符<<)代替了不同的輸入輸出函數名,如printf和scanf等。從直觀來看,這種改變使得IO語句更為簡明。另外,也減輕了程序員在記憶函數名和書寫程序上的一些負擔。例如:
printf(“n=%d,a=%f\n”,n,a); cout<<”n=”<<n<<”,a=”<<a<<endl;
雖然兩條語句的輸出結果是一樣的,但是后者更加簡明,直觀,易寫,易讀。
(2)類型安全(type safe)
所謂類型安全,是指編譯器所理解的數據實體(如變量。指針所指向的數據等)的類型,與實際數據實體的實際類型或對該數據所進行的操作之間保持一致性。在進行IO操作時,編譯器將自動檢查實參的表達式類型來調用IO流類相應的重載版本的成員函數,來完成輸入輸出。而采用C的IO函數,必須顯示指明操作的數據類型,如采用printf()函數,由于其參數中的數據類型必須由程序員以參數格式%d,%f,%c,%s,容易出錯。
(3)易于擴充
C++語言的IO流類庫,是建立在類的繼承關系、模板和操作符重載等機制的基礎上的。把原來C語言中的左、右移位運算符<<和>>,通過運算符重載的方法,定 義為插入(輸出)和提?。ㄝ斎耄┻\算符。這就為輸入輸出功能對于各種用戶定義的類型數據的擴充,創(chuàng)造了方便的條件。
用戶可以采用輸入輸出操作符的重載來完成用戶想要的輸入輸出功能。例如,用于復數類Complex的輸出操作符重載函數可以定義為:
friend ostream& operator<<(ostream& s,const Complex& c){ s<<c.real<<"+"<<c.image<<"i"<<endl; return s; }
輸入輸出操作符有個固定的格式,以上是一種常用的格式。由于C語言并不支持函數重載,也不直接支持面向對象的程序設計,所以想擴充C語言的輸入輸出函數使它們支持用戶定義的新數據類型,是一件非常困難的事情。
以上就是淺談C++ IO流的詳細內容,更多關于C++ IO流的資料請關注腳本之家其它相關文章!