JAVA-IO流體系

JAVA-IO流體系

在IO中,具體構件角色是節點流,裝飾角色是過濾流。
1、繼承自InputStream/OutputStream的流都是用於向程序中輸入/輸出數據,且數據的單位都是字節(byte=8bit),如圖,深色的爲節點流,淺色的爲過濾流。
在這裏插入圖片描述
2、繼承自Reader/Writer的流都是用於向程序中輸入/輸出數據,且數據的單位都是字符(2byte=16bit),如圖,深色的爲節點流,淺色的爲過濾流。
在這裏插入圖片描述
從圖中可以看出,InputStream就是裝飾者模式中的超類(Component),ByteArrayInputStream,FileInputStream相當於被裝飾者(ConcreteComponent),這些類都提供了最基本的字節讀取功能。而另外一個和這兩個類是同一級的類FilterInputStream即是裝飾者(Decorator),BufferedInputStream,DataInputStream,PushbackInputStream…這些都是被裝飾者裝飾後形成的成品。

爲什麼可以說:裝飾模式可以在不創造更多子類的情況下,將對象的功能加以擴展,能理解這一點就能很好的掌握裝飾者設計模式的精髓,如果在InputStream這裏擴展出FilterInputStream類下面的裝飾類,那麼針對FileInputStream和ByteArrayInputStream就都要去實現一次BufferedInputStream了,那麼可能就會衍生出BufferedFileInputStream和BufferedByteArrayInputStream這樣的類,如果按照這樣的擴展方式去添加功能,對於添加功能的子類來說簡直是一場噩夢,好在裝飾着模式很好的解決了這個問題,現在我們只需要在過濾流類這裏維護一個超類,不論傳入的是什麼具體的節點流,那麼都只要套一層裝飾,就能對功能方法進行加強。

如果想要對文件輸入流進行緩存加強可以這樣裝飾:

File file = new File ("hello.txt"); 
BufferedInputStream inBuffered=new BufferedInputStream (new FileInputStream(file));

如果想要對字節數組輸入流進行緩存加強可以這樣裝飾:

byte[] byts="Hello".getBytes();
BufferedInputStream bf=new BufferedInputStream(new ByteArrayInputStream(byts));

那麼節點流上的類就可以平行擴展,而裝飾者同樣可以按照功能進行另外一個維度的擴展,調用的時候就可以按需進行組合裝飾,這樣就可以減少了子類還將對象的功能進行擴展,不得不佩服前人在該設計模式上的智慧,理解了這裝飾着模式後,就應該對java中IO流的體系進行梳理:

節點流類型

  • 對文件操作的字符流有FileReader/FileWriter,
  • 字節流有FileInputStream/FileOutputStream。

過濾流類型

  • 緩衝流:緩衝流要“套接”在相應的節點流之上,對讀寫的數據提供了緩衝的功能,提高了讀寫效率,同時增加了一些新的方法。
    • 字節緩衝流有BufferedInputStream / BufferedOutputStream,字符緩衝流有BufferedReader / BufferedWriter,字符緩衝流分別提供了讀取和寫入一行的方法ReadLine和NewLine方法。
    • 對於輸出的緩衝流,寫出的數據,會先寫入到內存中,再使用flush方法將內存中的數據刷到硬盤。所以,在使用字符緩衝流的時候,一定要先flush,然後再close,避免數據丟失。
  • 轉換流:用於字節數據到字符數據之間的轉換。
    • 字符流InputStreamReader / OutputStreamWriter。其中,InputStreamReader需要與InputStream“套接”,OutputStreamWriter需要與OutputStream“套接”。
  • 數據流:提供了讀寫Java中的基本數據類型的功能。
    • DataInputStream和DataOutputStream分別繼承自InputStream和OutputStream,需要“套接”在InputStream和OutputStream類型的節點流之上。
  • 對象流:用於直接將對象寫入寫出。
    • 流類有ObjectInputStream和ObjectOutputStream,本身這兩個方法沒什麼,但是其要寫出的對象有要求,該對象必須實現Serializable接口,來聲明其是可以序列化的。否則,不能用對象流讀寫。(api以及demo在文末)
重點梳理一下:Java中Inputstream/OutputStream與Reader/Writer的區別
  • Reader/Writer和InputStream/OutputStream分別是I/O庫提供的兩套平行獨立的等級機構,
    • InputStream、OutputStream是用來處理8位元的流,也就是用於讀寫ASCII字符和二進制數據;Reader、Writer是用來處理16位元的流,也就是用於讀寫Unicode編碼的字符。
    • 在JAVA語言中,byte類型是8位的,char類型是16位的,所以在處理中文的時候需要用Reader和Writer。
    • 兩種等級機構下,有一道橋樑InputStreamReader、OutputStreamWriter負責進行InputStream到Reader的適配和由OutputStream到Writer的適配。
  • 在Java中,有不同類型的Reader/InputStream輸入流對應於不同的數據源:
    • FileReader/FileInputStream 用於從文件輸入;
    • CharArrayReader/ByteArrayInputStream 用於從程序中的字符數組輸入;
    • StringReader/StringBufferInputStream 用於從程序中的字符串輸入;
    • PipedReader/PipeInputStream 用於讀取從另一個線程中的 PipedWriter/PipeOutputStream 寫入管道的數據。
    • 相應的也有不同類型的Writer/OutputStream輸出流對應於不同的數據源:FileWriter/FileOutputStream,CharArrayWriter/ByteArrayOutputStream,StringWriter,PipeWriter/PipedOutputStream。
IO流的應用選擇

確定選用流對象的步驟

  • 確定原始數據的格式
  • 確定是輸入還是輸出
  • 是否需要轉換流
  • 數據的來源(去向)
  • 是否需要緩衝
  • 是否需要格式化輸出
特殊需求
  • 從Stream轉化爲Reader,Writer:InputStreamReader,OutputStreamWriter
  • 對象輸入輸出流:ObjectInputStream,ObjectOutputStream
  • 進程間通信:PipeInputStream,PipeOutputStream,PipeReader,PipeWriter
  • 合併輸入:SequenceInputStream
  • 更特殊的需要:PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章