[三]JavaIO之IO體系類總體設計思路 流的概念以及四大基礎分類

從本文開始,將正式進入JavaIO的簡介
在繼續javaIO系列的文章以前
能夠過去看一下 本人博客上的設計模式中的 適配器模式和裝飾器模式
這會對接下來的閱讀大有幫助
 
本文是從邏輯上介紹整個的Java IO類家譜畫像.
 

1.流

 
計算機以及互聯網的世界發展不太短短几十年,可是這幾十年倒是突飛猛進
系統的複雜度也愈來愈高,程序設計語言的抽象程度也愈來愈高
可是不管如何都繞不開一個話題,那就是IO
以前已經介紹過,IO 就是輸入 和 輸出, 入和出是相對於應用程序來講的
並且,常常一個程序的輸出多是另外一個程序的輸入
這自己就是一個抽象的概念
並無"必須怎麼樣,那才叫IO"的說法
從數據庫,從文件,從內存,從網絡拿數據,你均可以叫作輸入,數據寫出,均可以叫作輸出,這並無什麼好糾結的
 
在java中使用流這一律念來描述輸入和輸出

流的字面含義

image_5b94b200_4459
百度百科中是這樣描述流的, 能夠看得出來 , 流自己就包含了 這樣一層含義 
物質      一個地方      流向了      另外一個地方
 
在繼續以前,咱們先回想下放暑假或者開學時候的場景
假定你須要作汽車和火車,以下圖所示
image_5b94b200_4484
 
上圖中有幾個關鍵概念
主體 人     人從一個地方到了另外一個地方
源/目的      學校/家
方向 回家或者返校       圖中的兩個箭頭
中間形式 火車和汽車

1.1流究竟是什麼

 
咱們再舉一個比較簡單的例子, 使用 水管 往桶裏面加水或者抽水
 
源/主體內容/方向
水桶, 做爲一個容器,他就是  源
裏面可能裝了水,也可能裝了酒,還可能裝了別的, 這就是數據形式主體
箭頭表示方向,究竟是往裏面流仍是往外抽
 
image_5b94b200_7e4f
中間形式
咱們都知道,水管可不全都是一種規格的,就拿家裏裝修經常使用的水管就有 4/6分管 兩種
若是有一個閥門或者水龍頭是6分管,而你接入桶裏面的是4分管
怎麼辦?
顯然,你會找一個轉接頭一類的東西,這就是下圖中的黃色,橙紅色,綠色表明的部分,他們就是不一樣的水管
經過轉接頭與另一種規格的水管可以鏈接起來,這就是中間形式
image_5b94b200_63b
抽水模型中的流
在這個例子中,流就是對於抽水這一過程的抽象描述.
一個水管裏面的水的走向, 設定好了以後, 就是固定了的, 他要麼往這頭, 要麼往另外一頭
並且,他確定有一個源頭/目的,水管得水不能憑空來,水管也不能憑空抽取水
另外,水管顯然不只僅只是能抽取水, 他還能夠輸送別的液體,好比酒,水,飲料,醬油醋......
並且,若是有了各類不一樣規格的水管以及轉接頭,你的這個管道將會更增強大

因此說,容器 桶 接上了水管,就有能力提供水或者存儲水,他就是一個流
若是這個流在整合上各類不一樣規格的轉接頭和水管,能力將會大大提高

1.2程序語言中的流的主要概念

含義/源/方向/數據形式/中間形式
流的含義:
在程序設計中,流是對於數據流動傳輸的一種抽象描述
任何有能力產出數據的數據源,或者有能力接受數據的接收端對象都是一個流 (也就是上面例子中的一個容器接上水管)
流的源和目的:
數據可能從本地文件讀取,或者寫入,  也可能發送到網絡上,這就是源和目的
流的方向:
同水管裏面的流水同樣,也是隻有兩個方向,流進或者流出,也就是咱們常說的輸入  和  輸出
流的數據形式:
數據的具體形式就是流傳送的內容,多是字節,也能是字符,這就是數據的形式
流的中間形式:
對於任何一個流對它的功能進行一些必要的擴充,就好像接上了轉接頭的流能夠接到其餘規格的水管同樣
在一個流的基礎上 包裝,裝飾上其餘的一些功能,流就會變得更增強大

1.3 流相關概念詳細解讀

 

1.3.1 流的源和目的

1.文件
最基本的一個數據源就是咱們前文提到過的文件,文件不只java中有,其餘語言中也擁有文件的概念
2.字節數組
數據最基本的單位是字節
數組是在程序設計中,爲了處理方便, 把具備相同類型的若干變量按有序的形式組織起來的一種形式
這些按序排列的同類數據元素的集合稱爲數組
因此字節數組,天然是爲了更方便操做字節的一種數據組織形式
3. 字符數組/String對象
既然數組能夠簡化更方便的進行操做,並且也有字節數組
是否是還應該有字符數組呢?
並且,java中的String對象 ,它的內部實現也是char數組,java中使用char表示字符,這不就是字符數組麼
4. 管道
"管道"的概念也是相似字面含義,一端輸入,就能夠從一端流出,就好像一個水管同樣,
主要用來多線程之間直接進行數據交互,因此說數據來源也多是一個管道
5.網絡等
其餘數據源好比網絡等,java的強項就是WEB,從網絡接收數據是再天然不過的事情
6.流
另外流自己也能夠做爲一種源,因此一個流的源能夠來自另外的一個流
 

1.3.2 流的方向

流的方向很簡單,只有兩個方向,輸入 或者 輸出
 

1.3.3 流的數據形式

計算機存儲數據是二進制的 0 1 序列
計算機中存儲容量的最小的單位是位(bit)最基本的單位是 字節 (byte)
字節是經過網絡傳輸信息(或在硬盤或內存中存儲信息)的單位
也就是說任何其餘形式的數據,均可以並且,最終也都是用字節來表示
因此數據最基本的形式就是字節 
1  byte = 8 bit  
咱們的世界充滿了各類符號
字符是表示數據和信息的字母、數字或其餘符號
在電子計算機中,每個字符與一個二進制編碼相對應,這是一個編碼的過程
因此說,數據的基本形式有  字節 和 字符兩種形式

1.3.4流的中間形式

放學回家的例子,咱們很清楚的知道,火車和汽車是咱們 人的中間形式過程,通過轉換(買票上車),  地上的人看不到咱們了,看到的只是火車
對於流來講,中間形式是什麼樣子的呢?
好比咱們想要把一個Int類型直接寫入到文件中,怎麼辦呢?
咱們是否是須要把這個類型的數據處理下 轉換下呢  或者說包裝下 就如同你坐上了車(車把你裝了進去,形式就是車),總之就是要處理下
好比想要緩衝,按照行,按照字等等
這就是一種中間形式,後面咱們會詳細介紹涉及到的中間形式
不過很顯然,中間形式並無向從某種數據源讀取數據那麼剛需
可是他會給你提供更多的功能,讓你的流功能更加多變,擴展
若是有了中間形式,你可能就可以直接把一個int寫入到文件上,這不是很方便麼 

1.3.5流的種類-基本功能 擴展功能

想要完成一個IO類庫的基本功能,只須要把握住三點
1. 流的源和目的
2. 流的數據形式 
3. 流的方向  
想要作得更好就須要把握好流的中間形式,提供更強大的功能
 
 
流的源和目的 文件 / 字節數組 /管道 /字符數組/String對象 / 網絡 / 流
流的數據形式 字符  /  字節
流的方向 輸入  / 輸出
如今咱們掌握了流的基本屬性,上表中的三種,也掌握了他們可能的變量值 
很簡單,只須要使用簡單的組合進行計算,咱們就能夠列舉出來全部可能的組合
下面咱們試着列一些(並不會列出來所有內容)
文件(源) 輸入        字節              
文件(源) 輸入 字符
文件(目的地) 輸出 字節
文件(目的地) 輸出 字符
字節數組(源) 輸入 字節
字節數組(源) 輸入 字符
字節數組(目的地) 輸出 字節
字節數組(目的地) 輸出 字符
管道(源) 輸入 字節
管道(源) 輸入 字符
管道(目的地) 輸出 字節
管道(目的地) 輸出 字符
 
等等................等等................
還有不少種組合,   我相信你確定能夠排列的出來
不過很顯然,咱們此處只是簡單的羅列,窮舉出全部組合的可能
對於類庫的設計天然不能這麼簡單暴力,或許有些組合沒有必要,或許有些組合不符合邏輯
去掉那些無用的,不合邏輯的,無心義的,那麼剩下來的組合形式,其實就是IO類庫要解決的問題
也就是就剩下了咱們如今看獲得的JavaIO類庫了 接下來從總體上對IO類庫進行介紹

2. JAVA  IO類庫體系結構

java.io
 
image_5b94b200_5fdd
 
java.io包中(JDK8),有87個類,其中有一些輔助類 還有一些異常類
去掉這些以後,剩下的絕大多數都是IO類體系的直接相關類,看起來很雜亂繁多
咱們接下來說從總體上對涉及到的IO類進行介紹,等看完本篇文章,相信你應該能有一個總體的把控
只有從總體把控纔有可能掌握整個完整的類家族

2.1 流的四你們族

若是先不考慮數據的來源,根據流的方向(輸入 和 輸出)以及流的數據形式(字符 和 字節) 咱們有四種形式
輸入 字節
輸出 字節
輸入 字符
輸出 字符
 
 
四種形式 輸入字節  輸出字節  輸入字符   輸出字符
Java中名稱 InputStream OutPutStream Reader Writer
 
能夠看得出來在命名上,類庫設計者的一些想法
把字節使用Stream做爲後綴,或許由於字節是最基本的單位,因此他纔是流Stream
咱們平時閱讀  read和書寫write的都是字符,因此使用Reader 和 Writer表示字符的輸入和輸出也很天然
image_5b94b201_583f
 

節點流與過濾流

咱們上面講述流的含義概念時,反覆提到了流的基本功能以及中間形式
基本功能就是針對於不一樣數據源的操做,屬於剛需範圍
而中間形式則是剛需的強有力的加強
流的數據源/目的  流的方向  流的數據類型的組合,構成了基本功能的完整集合
而對於加強型的流的形式,則是Java IO出彩的地方,屬於加強型的功能
java中針對於基本數據源進行操做的流叫作 節點流
而對於那些起到加強裝飾功能的流,叫作 過濾流
 
按照咱們上面的思惟邏輯
只須要把相關的數據源與咱們上面的這四種基本形式進行組合
就能夠獲得流的基本功能家族,也就是節點流
根據節點流須要的拓展功能,咱們就能夠推演出來過濾流
 
2.2  流體系類層次結構詳解
 

2.2.1  InputStream

 

2.2.1.1  InputStream節點流

 
數據源與InputStream的結合
字節數組 ByteArrayInputStream (java.io)
文件
FileInputStream (java.io)
管道
PipedInputStream (java.io)
String
StringBufferInputStream (java.io)  
對象 ObjectInputStream (java.io)
上面就是IO類庫提供給咱們的基礎功能
也就是可用的有效的合理的數據源與InputStream的組合(InputStream  流的方向與流的數據形式的組合)
類名 功能 構造方法
ByteArrayInputStream 從字節數組中讀取數據,也就是從內存中讀取數據
包含一個內部緩衝區,指向該字節數組
內部計數器跟蹤 read 方法要提供的下一個字節
關閉 ByteArrayInputStream 無效
此類中的方法在關閉此流後仍可被調用,而不會產生任何 IOException
ByteArrayInputStream(byte buf[])
ByteArrayInputStream(byte buf[], int offset, int length)
不是複製而來,直接指向地址
多參數的帶偏移量
FileInputStream 用於從文件中讀取信息 FileInputStream(String name)
FileInputStream(File file)
FileInputStream(FileDescriptor fdObj)
使用文件路徑名  抽象路徑名File 或者文件描述符
PipedInputStream 產生用於寫入相關Pipe的OutputStream的數據
實現管道化的概念
管道輸入流應該鏈接到管道輸出流;
管道輸入流提供要寫入管道輸出流的全部數據字節

一般,數據由某個線程從 PipedInputStream 對象讀取
並由其餘線程將其寫入到相應的 PipedOutputStream
不建議對這兩個對象嘗試使用單個線程,由於這樣可能死鎖線程
PipedInputStream(PipedOutputStream src)
PipedInputStream(PipedOutputStream src, int pipeSize)
PipedInputStream()
PipedInputStream(int pipeSize) 
StringBufferInputStream 棄用,若是條件容許能夠考慮使用StringReader
ObjectInputStream
對之前使用 ObjectOutputStream 寫入的基本數據和對象進行反序列化
ObjectOutputStream 和 ObjectInputStream 分別與 FileOutputStream 和 FileInputStream 一塊兒使用時
能夠爲應用程序提供對對象圖形的持久存儲
ObjectInputStream 用於恢復那些之前序列化的對象
其餘用途包括使用套接字流在主機之間傳遞對象,或者用於編組和解組遠程通訊系統中的實參和形參。
 
ObjectInputStream(InputStream in)
ObjectInputStream()
 
SequenceInputStream能夠說既不是節點流也不是過濾流,硬要算的話,能夠說是節點流 算是一個工具類同樣的存在
SequenceInputStream (java.io) 兩個或者多個InputStream對象轉換爲單一的InputStream SequenceInputStream(InputStream s1, InputStream s2)
SequenceInputStream(Enumeration<? extends InputStream> e)
 
image_5b94b201_33ff

2.2.1.2  InputStream過濾流

介紹過了InputStream的節點流,咱們看下,咱們還但願InputStream可以哪些擴展的功能,也就是上面提到過的 流的中間形式
咱們以前就提到過,但願可以有直接操做數據類型的流,經過這個流能夠直接操做基本數據類型的讀寫,而不須要本身去處理字節或者字節數組等
也就是說咱們但願可以對基本數據類型進行支持
IO是操做系統的瓶頸,若是過於頻繁的直接對磁盤IO進行讀寫,勢必會增長CPU的空閒,性能下降,咱們但願可以有緩衝的功能
IDE開發工具的編輯器都有行號的標誌,行號能夠給咱們提供不少的便捷性,因此但願可以跟蹤展現行號
好比當咱們用程序讀取一行代碼,識別其中的關鍵字
好比 int i = 0; 讀取到int時,咱們不知道他是否是關鍵字,多是一個int0的變量名
讀取到下一個的時候,發現是空格,咱們才能肯定,他就是一個關鍵字
可是下面的空格已經被讀取了,咱們可能但願接下來的掃描可以讀取到空格,但是流是順序的,被消費了就不存在了
因此但願可以把讀取到的字節回退到原來的流中
因而就有了 
支持基本數據類型/緩存/行號/回退  這幾種擴展功能的想法
 
功能點和InputStream組合下能夠獲得以下四種擴展功能  
Data表示基本數據類型  Buffer 表示緩衝  LineNumber表示行號 PushBack表示回退
DataInputStream (java.io)
BufferedInputStream (java.io)
LineNumberInputStream (java.io)
PushbackInputStream (java.io)
 
image_5b94b201_2db9
 
到底怎麼實現呢?
顯然咱們能夠直接經過實現InputStream來實現這幾個子類,用於表示這幾個功能
可是就又出現了一個問題,若是既想要 支持基本數據類型,又想具備緩衝的功能怎麼辦? 若是還用繼承的想法會出現什麼問題?
那就又回到了組合的問題上來了,4種功能就會出現4*3*2*1=24 中組合,類的個數直接爆炸了.....
 
回想下咱們以前想到過的設計模式---> 裝飾器模式
就能夠完美的解決這個問題,裝飾器模式是繼承的一種良好替代方式,能過有效的避免類的個數的爆炸問題
而且還可以動態的增長或者減小功能
看下UML圖
image_5b94b201_78e7
 
經過UML圖能夠看獲得,咱們還須要一個Decorator類,咱們的具體的裝飾類個數不止一個,顯然不能省略這個Decorator抽象類
(不清楚裝飾器模式的沒辦法理解這種邏輯,請務必看明白裝飾器模式)
這個Decorator就是咱們的FilterInputStream (java.io)  
看下類圖,黑色部分爲裝飾器模式的角色
節點流表示上面說到的節點流
ByteArrayInputStream/FileInputStream/PipedInputStream/ObjectInputStream/StringBufferInputStream

FilterInputStream中包含一個InputStream屬性(是你還有你)
image_5b94b201_17ba
image_5b94b201_7ddb


下面咱們看下InputStream下的類繼承體系
如今你是否已經能夠大體的明白,這些類都是作什麼的了呢?
image_5b94b201_789e

另外還有一些不在java.io包中的類
這些不是IO主體系內的東西,可是依賴於IO ,從事着跟IO相關的一些工做,因此也擴展自InputStream
後面將會單獨進行介紹,此處不展開討論
SocketInputStream (java.net)
CheckedInputStream (java.util.zip)
DeflaterInputStream (java.util.zip)
GZIPInputStream (java.util.zip)
InflaterInputStream (java.util.zip)
ZipInputStream (java.util.zip)
JarInputStream (java.util.jar)
image_5b94b201_6211
 
 

2.2.2 OutputStream

2.2.2.1  OutputStream節點流

 
數據源與OutputStream的結合
字節數組 ByteArrayOutputStream (java.io)
文件
FileOutputStream (java.io)
管道
PipedOutputStream (java.io)
對象 ObjectOutputStream (java.io)
 
仍舊是數據源與OutputStream的組合
ByteArrayOutputStream
其中的數據被寫入一個 byte 數組
緩衝區會隨着數據的不斷寫入而自動增加, 可以使用 toByteArray() 和 toString() 獲取數據
 
關閉 ByteArrayOutputStream 無效
此類中的方法在關閉此流後仍可被調用,而不會產生任何 IOException
ByteArrayOutputStream()
ByteArrayOutputStream(int size)
無參會調用有參,設置默認值
FileOutputStream 信息寫入文件 FileOutputStream(String name)
FileOutputStream(String name, boolean append)
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(FileDescriptor fdObj)
與FileInputStream幾乎同樣,不一樣的是第二個參數用於設置是不是append追加
PipedOutputStream 能夠將管道輸出流鏈接到管道輸入流來建立通訊管道
管道輸出流是管道的發送端
一般,數據由某個線程寫入 PipedOutputStream 對象
並由其餘線程從鏈接的 PipedInputStream 讀取
不建議對這兩個對象嘗試使用單個線程,由於這樣可能會形成該線程死鎖
PipedOutputStream(PipedInputStream snk)
PipedOutputStream()
ObjectOutputStream ObjectOutputStream 將 Java 對象的基本數據類型和圖形寫入 OutputStream
可使用 ObjectInputStream 讀取(重構)對象
經過在流中使用文件能夠實現對象的持久存儲
若是流是網絡套接字流,則能夠在另外一臺主機上或另外一個進程中重構對象
ObjectOutputStream(OutputStream out)
ObjectOutputStream()
 
image_5b94b201_34f3
 

2.2.2.2  OutputStream過濾流

相似InputStream,OutputStream也須要有支撐基本數據類型的功能,以及緩衝的功能
另外,既然是輸出,還但願可以輸出各類類型的數據,這樣子將會更加方便
也就是 
基本數據類型支持/緩衝/便捷輸出
DataOutputStream (java.io)
BufferedOutputStream (java.io)
PrintStream (java.io)
image_5b94b201_794b
 
同InputStream 同樣
擴展的功能,類庫設計者依然是使用裝飾器模式
FilterOutputStream (java.io)  是咱們的Decorator
image_5b94b201_7535
 
完整的家譜
 
image_5b94b202_66d1
 
 
非IO包中的,可是卻跟IO相關的一些功能點,跟OutputStream相關的類
SocketOutputStream (java.net)
CheckedOutputStream (java.util.zip)
DeflaterOutputStream (java.util.zip)
GZIPOutputStream (java.util.zip)
InflaterOutputStream (java.util.zip)
JarOutputStream (java.util.jar)
ZipOutputStream (java.util.zip)
 
擴展的家譜
image_5b94b202_6163
 

2.2.3 Reader

2.2.3.1  Reader節點流

數據源與Reader的結合
字符數組 CharArrayReader (java.io)
String StringReader (java.io)
文件
FileReader (java.io)
管道
PipedReader (java.io)
 
 
CharArrayReader 實現一個可用做字符輸入流的字符緩衝區 CharArrayReader(char buf[])
CharArrayReader(char buf[], int offset, int length) 
StringReader 其源爲一個字符串的字符流 StringReader(String s)
FileReader 用來讀取字符文件的便捷類 FileReader(String fileName)
FileReader(File file)
FileReader(FileDescriptor fd)
PipedReader 管道字符輸入流 PipedReader(PipedWriter src)
PipedReader(PipedWriter src, int pipeSize)
PipedReader()
PipedReader(int pipeSize) 
 
字節和字符做爲數據的存儲單位,天然常常有轉換的須要
InputStreamReader 就是InputStream 轉換爲Reader的類
InputStreamReader 轉換爲Reader
InputStreamReader 是字節流通向字符流的橋樑
它使用指定的 charset 讀取字節並將其解碼爲字符
它使用的字符集能夠由名稱指定或顯式給定,或者能夠接受平臺默認的字符集
每次調用 InputStreamReader 中的一個 read() 方法都會致使從底層輸入流讀取一個或多個字節
爲了達到最高效率,可要考慮在 BufferedReader 內包裝 InputStreamReader
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, String charsetName)
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, CharsetDecoder dec)
構造方法很清晰,接受一個InputStream 而且能夠自定義字符編碼
 
對於類的轉換,設計模式中使用了適配器模式
經過構造方法接收InputStream,而後經過內部的StreamDecoder處理
StreamDecoder  和 StreamEncoder  是做爲字符輸入和輸出轉換的關鍵類,後續有時間會介紹到
image_5b94b202_452d
image_5b94b202_1a39
 
屬於適配器模式中的對象適配器模式
Reader 是Target
InputStream   是 被適配者 Adaptee
InputStreamReader   是  Adapter 
 
須要注意的是,FileReader   與字節流中的FileInputStream 和 FileOutputStream 也是不同的
FileReader 繼承 InputStreamReader

2.2.3.2  Reader過濾流

字符流Reader也依然有裝飾器模式的應用
BufferedReader (java.io)
LineNumberReader (java.io)
PushbackReader (java.io)
 
image_5b94b202_6908
不過須要注意,Reader字符流的裝飾器模式應用跟字節流的有些差異
在字節流中,擴展功能都是經過FilterInputStream 或者 FilterOutputStream 
 
然而,在咱們的Reader中
BufferedReader  和 FilterReader 各自是一個裝飾器模式
在BufferedReader中,能夠理解爲只有一個具體的裝飾器的簡化版本
省略了抽象類
直接繼承自Reader
BufferedReader  融合了Decoder 和 ConcreteDecoder二者
 
image_5b94b202_6536
是你還有你 BufferedReader 是Reader 還有一個Reader
在FilterReader中就跟以前的字節流中的裝飾器模式的應用基本一致了
FilterReader 表示抽象的裝飾器部件  Decoder
PushbackReader 表示具體的裝飾器
image_5b94b202_7f8c
是你還有你  FilterReader 是 Reader 還有 Reader
 
Reader家族完整的族譜
image_5b94b202_69d9
 

2.2.4 Writer

數據源與writer的結合
字符數組 CharArrayWriter (java.io)
String StringWriter (java.io)
文件
FileWriter (java.io)
管道
PipedWriter (java.io)
 
 
CharArrayWriter
實現一個可用做 Writer 的字符緩衝區
緩衝區會隨向流中寫入數據而自動增加  可以使用 toCharArray() 和 toString() 獲取數據。
在此類上調用 close() 無效
而且在關閉該流後能夠調用此類中的各個方法,而不會產生任何 IOException
 
CharArrayWriter()
CharArrayWriter(int initialSize)
內部包含char buf[] size爲大小
構造方法用來初始化緩衝區
StringWriter 將輸出收集到一個字符緩衝區 StringBuffer的字符流,能夠用來構造字符串
關閉 StringWriter 無效
此類中的方法在關閉該流後仍可被調用,而不會產生任何 IOException
StringWriter()
StringWriter(int initialSize)
構造方法初始化緩衝區
FileWriter 用來寫入字符文件的便捷類
相似FileReader繼承自InputStreamReader
他繼承自OutputStreamWriter
FileWriter(String fileName)
FileWriter(String fileName, boolean append)
FileWriter(File file)
FileWriter(File file, boolean append)
FileWriter(FileDescriptor fd)
構造方法都是用來設置文件
PipedWriter 管道字符流 PipedWriter(PipedReader snk)
PipedWriter() 
 
轉換流
OutputStreamWriter 相似InputStreamReader 做爲轉換器使用
OutputStreamWriter 是字符流通向字節流的橋樑
可以使用指定的 charset 將要寫入流中的字符編碼成字節
使用的字符集能夠由名稱指定或顯式給定,不然將接受平臺默認的字符集
每次調用 write() 方法都會致使在給定字符(或字符集)上調用編碼轉換器
爲了得到最高效率,可考慮將 OutputStreamWriter 包裝到 BufferedWriter 中
例如:
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
 
OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out, Charset cs)
OutputStreamWriter(OutputStream out, CharsetEncoder enc)
獲取OutputStream而後進行轉換,或者指定具體的字符編碼
 
FilterWriter 相似其餘的Filter類,做爲裝飾器模式的Decoder角色
以便具體的裝飾器角色可使用

 
BufferedWriter   以及  PrintWriter相似Reader  不一樣於字節流的裝飾器模式應用
他們都自成一個模式的應用
他倆都單獨是Writer 也都包含一個Writer
image_5b94b202_d38
 
Writer下完整的家譜
image_5b94b202_11b8
 

2.3 IO類層次結構總結

 
前面已經對IO類的基本層次結構進行了一個邏輯上的概述
咱們如今概括歸納下一些基本特色
 
IO的邏輯功能設計點 由 數據源,流的方向,流的數據形式三部分組合而成,這個組合構成了IO的基本功能
另外還有擴展功能,擴展功能以基礎功能做爲依託,底層依賴基本功能
每種形式的基本功能和擴展功能構成了該形式的功能的集合
數據源形式比較多,可是對於流的數據形式以及流的方向是固定的
因此全部的類的基礎,都是基於  流的數據形式以及流的方向的組合
也就是 字節輸入 字節輸出   字符輸入  字符輸出
這四個形式是固定的
分別使用 InputStream  OutputStream  Reader  Writer來表示這四你們族
前面兩個表示字節  後面兩個表示字符
絕大多數的擴展都以 上面四個名詞做爲後綴,表示是他的家族成員
基本功能對於字節涉及下面幾個關鍵詞  
ByteArray   File  Piped  Object
擴展功能對於字節涉及涉及下面幾個關鍵詞 
Data  Buffered  Pushback  LineNumber print
基本功能對於字符涉及涉及下面幾個關鍵詞 
CharArray  String File  Piped
擴展功能對於字符涉及涉及下面幾個關鍵詞  
Buffered    Print
雖然四你們族都由基本功能以及擴展功能組成
可是字符和字節的實現形式卻並不徹底相同
字節流的擴展功能比較依賴裝飾器角色FilterInputStream  以及 FilterOutputStream
可是字符流的擴展功能不徹底依賴FilterReader  以及  FilterWriter
數據源與四你們族的結合組合成了基本功能  也就是節點流
擴展功能點與四你們族的結合組成了擴展功能 也就是過濾流
另外還有幾個工具同樣的存在
SequenceInputStream   用於合併InputStream
InputStreamReader 以及OutputStreamWriter 用於轉換 使用了適配器模式
 
本文主要是從邏輯上介紹了IO家族,雖然實現上都略有差別
可是基本的命名習慣和功能點四個家族是很是相似的
只有理解了類庫的邏輯出發點,才能理解IO整個的類庫,而本文正是從邏輯上去解讀類庫的設計
相關文章
相關標籤/搜索