流是一種抽象概念,它代表了數據的無結構化傳遞。按照流的方式進行輸入輸出,數據被當成無結構的位元組序或字元序列。從流中取得數據的操作稱為提取操作,而向流中添加數據的操作稱為插入操作。用來進行輸入輸出操作的流就稱為IO流。換句話說,IO流就是以流的方式進行輸入輸出。
基本介紹
- 中文名:輸入輸出流
- 外文名:Input Output Stream
- 領域:計算機編程
- 程式語言:C++
概念,表示形式,步驟,組成結構,優點,
概念
輸入輸出(IO)與流的概念
輸入輸出(IO)是指計算機同任何外部設備之間的數據傳遞。常見的輸入輸出設備有檔案、鍵盤、印表機、螢幕等。數據可以按記錄(或稱數據塊)的方式傳遞,也可以 流的方式傳遞。
所謂記錄,是指有著內部結構的數據塊。記錄內部除了有需要處理的實際數據之外,還可能包含附加信息,這些附加信息通常是對本記錄數據的描述。
C++IO流,特指以流的方式進行輸入輸出的ISO/ANSI標準C++庫的輸入輸出類庫,也就是專門負責處理IO操作的一套系統。任何需要傳遞的數據,都要經過這套系統的處理。
表示形式
IO操作的過程中,任何需要被傳遞的數據,在經過IO類庫處理前後是不同的。這樣,我們可以把數據的表示分為兩種:內部表示和外部表示。
數據的內部表示便於程式進行數據處理。典型的內部表示有:整型數的二進制表示、浮點數的IEEE表示、字元的ASCII或Unicode編碼表示。數據的外部表示則根據不同的外部設備的需要,有具體不同的表現形式。如果外部數據表示是可讀的字元序列,則稱為文本IO,否則為二進制IO。標準IO流的主要目的是支持文本IO,不直接支持二進制IO。
雖然IO流是以流的方式進行數據傳遞,但這並不表明傳遞的數據不能有任何結構,而是指IO流的概念是以流的方式進行輸入輸出,所傳遞數據的內部結構隱藏在對流數據的解釋中。
步驟
在IO流里,輸入輸出分為4步:格式化/解析,緩衝,編碼轉換和傳遞。
格式化/解析:在內部數據表示(以位元組為單位)與外部數據表示(以字元為單位)之間進行雙向轉換。例如一個2位元組的整數10002,就需要5個字元來表示。
緩衝:用於在格式/解析與傳遞之間快取字元序列。對於輸出,較短的字元序列格式化之後並不馬上輸出,而是保存在緩衝區里,待累積到一定規模之後再傳遞到外部設備。相反,從外部設備讀入的大量數據也是先放在緩衝區,然後逐步取出完成輸入。默認時,IO流的輸入輸出都是經過緩衝的,也可以讓IO流工作在無緩衝模式下。
編碼轉換: 是將一種字元表達式轉換成另一種字元表達式。如果格式化產生的字元表達式與外部字元表達式不同(輸出時),或者外部表達式與IO流能解析的表達式不同(輸入時),就必須進行編碼轉換。如多位元組編碼與寬字元編碼之間的轉換等。多數情況下並不需要進行編碼轉換。
傳遞:主要是與外部設備進行通信。輸出時,傳遞負責將經過格式化、緩衝即編碼轉換後的字元序列傳送到外部設備;輸入時,則負責將外部設備抽取數據,為其後進行的編碼轉換、緩衝及解析提供字元序列。
組成結構
IO流類庫在不同平台的具體實現上,可能會有所變化,但從總體設計上來看,C++流庫主要由兩個流類層次組成:
(1)以streambuf類為父類的類層次
主要完成信息通過緩衝區的交換。派生層次如下:
緩沖區:是一個佇列數據結構,由一字元序列和兩個指針組成,這兩個指針分別指向字元要被插入或被取出的位置。
streambuf類為所有的streambuf類層次對象設定了一個固定的記憶體緩衝區,動態劃分為兩部分:
用做輸入的取區,用取指針指示當前取字元位置。
用做輸出的存區,用存指針指示當前存字元位置。
(2)以ios類為父類的類層次
ios類及其派生類是在streambuf類實現的通過緩衝區的信息交換的基礎上,進一步增加了各種格式化的輸入/輸出控制方法。它們為用戶提供使用流類的接口,它們均有一個指向streambuf的指針。
ios類有四個直接派生類:
istream
ostream
fstreambase
strstreambase
這四種流作為流庫中的基本流類。ios類的派生層次如下:
優點
C++語言開發了自己的IO流類庫,用以取代C語言的基本輸入輸出函式族。對於有經驗的C程式設計師來說,C語言提供的IO函式館時有效且方便的。但是,C語言的IO函式館有其自身的缺點,特別是在C++這種面向對象的程式設計語言中,C語言函式館無法直接支持面向對象的程式設計。因此,C++語言開發自己的IO流類庫是必然的。具體來說,IO流類庫具有以下優點。
(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語言中的左、右移位運算符<<和>>,通過運算符重載的方法,定 義為插入(輸出)和提取(輸入)運算符。這就為輸入輸出功能對於各種用戶定義的類型數據的擴充,創造了方便的條件。
用戶可以採用輸入輸出操作符的重載來完成用戶想要的輸入輸出功能。例如,用於複數類Complex的輸出操作符重載函式可以定義為:
friend ostream& operator<<(ostream& s,const Complex& c){ s<<c.real<<"+"<<c.image<<"i"<<endl; return s;}
輸入輸出操作符有個固定的格式,以上是一種常用的格式。由於C語言並不支持函式重載,也不直接支持面向對象的程式設計,所以想擴充C語言的輸入輸出函式使它們支持用戶定義的新數據類型,是一件非常困難的事情。