設計模式中巧記I/O

bbworld發表於2020-04-19

一、I/O

1. I/O操作中的設計模式

  1. 概要
  • 以設計模式角度,自頂向下理解I/O原始碼結構
  • 理解位元組與字元的關係
1.1 裝飾者模式(輸入流為例)
  1. 背景:通過繼承擴充套件物件耦合度高,使用裝飾者擴充套件可以在不改變現有結構的情況下,動態地給物件增加額外功能,耦合度底且靈活,一個具體物件可以有多個裝飾者
  2. 位元組流

  • 抽象構件 :第二行,InputStream介面,定義位元組流的基本操作
  • 抽象裝飾者 :第三行,與抽象構建介面是組合關係,動態的傳入具體構件。第四行通過擴充套件抽象構件子類,為具體構件新增新的功能
  • 具體構件 :第一行,實現抽象構件 操作,具體裝飾者 為每一個具體的構件新增新的職責
  • 具體裝飾者 :第四行,有新職責的具體構建
  1. 裝飾者模式為位元組流帶來的增強
    1. 使用InputStream 時,是以一個位元組一個位元組形式讀或寫,而BufferedInputStreamBufferedOutputStream 為位元組流提供了緩衝區,讀資料時一次性讀取一塊資料放到緩衝區中,當快取區讀取完後,輸入流會再次填充緩衝區,直到輸入流被讀取完,緩衝區可以減少IO操作。
    1. DataInputStream ,從位元組流中靈活的讀取並重建Java的基本型別與String型別資料
1.2 介面卡模式(輸入流為例)
  1. 背景:需要開發的業務功能在元件庫中已經存在,但與新的介面規範不相容,重新開發成本太高,所以使用介面卡模式能解決這些問題
  • 已有字元流讀寫介面ReaderWriter ,新的需求是位元組流訪問資料來源,然後由字元流處理
  1. 為什麼使用自符流
    1. 根本原因:記憶體中資料操作是以位元組為單位(給機器看的);一般持久化到磁碟不同的編碼對應不同的字元(給人類看的),也可以以位元組形式持久化到硬碟,供軟體與硬體閱讀。
    1. 位元組流操作單元為位元組(8byte)。InputStream中的read()方法,是以一個位元組為單位讀取,讀到末尾返回-1 、它的過載方法read(byte[])內部是通過for迴圈呼叫read() 實現一次讀入一個位元組陣列 ,按位元組的read()方法的會有頻繁IO操作,普通IO模型也會阻塞執行緒,直到返回一個位元組資料或-1,效率太低
    1. 字元流操作單元為Unicode碼點(16byte),使用快取讀寫。將資料持久化到磁碟 ,使用位元組寫入會亂碼,因為不同語言(漢語、英語等)都有自己對應的編碼表,例如英文一個字母可以用一個位元組表示,但漢語需要用兩個位元組,甚至一些特殊符號需要更多位元組(Unicode的輔助字元),一個位元組一個位元組寫入很大可能會亂碼。所以字元符流會先根據對應的碼錶將內容寫入緩衝區,緩衝區滿了持久化到磁碟。使用字元流有兩個好處
      1. 利用快取讀寫,避免記憶體與作業系統頻繁IO操作,提高效率
      1. 寫入時指定編碼表可以有效避免亂碼問題
  1. 介面卡模式中字元流與位元組流

  2. 字元流

  • Reader

  • Writer

-PS:個人筆記,望讀者勘誤。本文只例舉了位元組輸入流與字元輸入流兩種,若讀者理解了可以結合原始碼看輸出流中設計模式

相關文章