Java IO流詳解(一)----IO流簡單介紹


1、什么是IO

我們在生活中一定遇到這樣的情況,比如我們在編輯某個文件的時候,一時忘記了按 Ctrl+S 鍵,但是此時電腦恰好出現意外情況,就會導致我們的文件白白編輯了,如果文件不重要倒還好,如果是重要文件你估計會非常的氣憤。之所以一旦出現意外情況我們編輯的文件就沒了呢?這是因為我們編輯的新文件還保存在內存中,沒有將數據保存至硬盤中,那么我們應該通過 Ctrl+S 將數據從內存存儲至硬盤中。我們把這種數據的傳輸,可以看做是一種數據的流動,按照流動的方向,以內存為基准,分為輸入Input 和輸出Output ,即流向內存是輸入流,流出內存的輸出流,統稱為 IO流。 Java中I/O操作主要是指使用java.io包下的內容,進行輸入、輸出操作。輸入也叫做讀取數據,輸出也叫做作寫出數據。

image

 

2、流的概念和作用

流:代表任何有能力產出數據的數據源對象或者是有能力接受數據的接收端對象

流的本質:數據傳輸,根據數據傳輸特性將流抽象為各種類,方便更直觀的進行數據操作。

作用:為數據源和目的地建立一個輸送通道

 

3、IO流的分類

①、根據數據流向不同分為:輸入流和輸出流。

       輸入:讀取外部數據(磁盤、光盤等存儲設備的數據)到程序(內存)中。如InputStream,Reader

       輸出:把程序(內存)中的內容輸出到磁盤、光盤等存儲設備中。如OutputStream、Writer

 

②、根據處理數據類型的不同分為:字節流和字符流。

        字節流:可以用於讀寫二進制文件及任何類型文件。

        字符流:可以用於讀寫文本文件。

 

字節流和字符流的區別

字符流的由來: Java中字符是采用Unicode標准,一個字符是16位,即一個字符使用兩個字節來表示。為此,JAVA中引入了處理字符的流。因為數據編碼的不同,從而有了對字符進行高效操作的流對象。本質其實就是基於字節流讀取時,去查了指定的碼表。

兩者的區別:(1字符 = 2字節 、 1字節(byte) = 8位(bit)  、 一個漢字占兩個字節長度)

  1. 讀寫單位不同:字節流以字節為單位,字符流以字符為單位,根據碼表映射字符,一次可能讀多個字節。
  2. 處理對象不同:字節流能處理所有類型的數據(如圖片、avi等),而字符流只能處理字符類型的數據。
  3. 緩存不同:字節流在操作的時候本身是不會用到緩沖區的,是文件本身的直接操作的;而字符流在操作的時候下后是會用到緩沖區的,是通過緩沖區來操作文件。

總結:優先選用字節流。因為硬盤上的所有文件都是以字節的形式進行傳輸或者保存的,包括圖片等內容。字符只是在內存中才會形成的,所以在開發中,字節流使用廣泛。除非處理純文本數據(如TXT文件),才優先考慮使用字符流,除此之外都使用字節流。

 

③、根據功能的不同分為:節點流和處理流。

     節點流:可以從或向一個特定的地方(節點)讀寫數據。如FileInputStream,FileReader。

     處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調用實現數據讀寫。如BufferedReader。處理流的構造方法總是要帶一個其他的流對象做參數。一個流對象經過其他流的多次包裝,稱為流的鏈接。

     節點流是直接作用在文件上的流,可以理解為一個管道,文件在管道中傳輸。

     處理流是作用在已有的節點流基礎上,是包在節點流的外面的管道(可多層),其目的是讓管道內的流可以更快的傳輸。

image

Java的IO模型設計非常優秀,它使用裝飾模式(Decorator Pattern)[這篇博文詳細說明了什么是裝飾者模式 傳送門 ],這種設計是也稱為包裝模式(Wrapper Pattern),其使用一種對客戶端透明的方式來動態地擴展對象的功能,它是通過繼承擴展功能的替代方案之一。在現實生活中你也有很多裝飾者的例子,例如:人需要各種各樣的衣着,不管你穿着怎樣,但是,對於你個人本質來說是不變的,充其量只是在外面加上了一些裝飾,有,“遮羞的”、“保暖的”、“好看的”、“防雨的”.....。例如:您需要一個具有緩沖的文件輸入流,則應當組合使用FileInputStream和BufferedInputStream,而流的本身是不變的。

 

4、IO流中的基類

四個基本的抽象流類型,所有的流都繼承這四個。

下圖是Java IO流的整體架構圖,后面的博客會詳細的講解這些流使用: 

image

當看到上面這張圖的時候會感到很懵逼,因為這么多的類在使用時是選擇字節流輸入輸出還是選擇字符流輸入輸出呢?其實並不難。

  1. 如果你要將磁盤光盤中的數據讀到程序中,那就選擇輸入流,反之則是輸出流。
  2. 如果你要傳輸的是音頻視頻數據,那就肯定是字節流。如果單獨是純文本文件(如TXT),那就字符流。其實所有數據都可以使用字節流,只是效率高低問題。
  3. 如上面兩個都確定了,就可以選出一個合適的節點流,然后再根據你的需求是否需要額外功能(比如是否需要轉換流、高效流等)。

image

5、IO流常用到的五類一接口

Java IO流中所有的接口和類都放在java.io這個包下。其中最重要的就是5個類和一個接口。5個類指的是File、OutputStream、InputStream、Writer、Reader;一個接口指的是Serializable。如掌握了這些IO的核心使用方法,那么就能把Java IO流玩弄於股掌之中,將它放在手中任意盤它

它們的詳細介紹如下:

①. File(文件特征與管理):File類是對文件系統中文件以及文件夾進行封裝的對象,可以通過對象的思想來操作文件和文件夾。 File類保存文件或目錄的各種元數據信息,包括文件名、文件長度、最后修改時間、是否可讀、獲取當前文件的路徑名,判斷指定文件是否存在、獲得當前目錄中的文件列表,創建、刪除文件和目錄等方法。 

②. InputStream(二進制格式操作):抽象類,基於字節的輸入操作,是所有輸入流的父類。定義了所有輸入流都具有的共同特征。

③. OutputStream(二進制格式操作):抽象類。基於字節的輸出操作。是所有輸出流的父類。定義了所有輸出流都具有的共同特征。

④. Reader(文件格式操作):抽象類,基於字符的輸入操作。

⑤. Writer(文件格式操作):抽象類,基於字符的輸出操作。

⑥. RandomAccessFile(隨機文件操作):一個獨立的類,直接繼承至Object.它的功能豐富,可以從文件的任意位置進行存取(輸入輸出)操作。

⑦. Serializable(序列化操作):是一個空接口,為對象提供標准的序列化與反序列化操作。

6、Java IO流對象介紹

①、字節輸入流InputStream

image

根據上圖介紹各個類的作用:

  1. InputStream:字節輸入流基類,是所有的字節輸入流的父類,它是一個抽象類。
  2. FileInputSream:文件輸入流。它通常用於對文件進行讀取操作。
  3. FilterInputStream :過濾流。作用是為基礎流提供一些額外的功能。裝飾者模式中處於裝飾者,具體的裝飾者都要繼承它,所以在該類的子類下都是用來裝飾別的流的,也就是處理類。
  4. BufferedInputStream:緩沖流。對處理流進行裝飾,增強,內部會有一個緩存區,用來存放字節,每次都是將緩存區存滿然后發送,而不是一個字節或兩個字節這樣發送。效率更高。
  5. DataInputStream:數據輸入流。它是用來裝飾其它輸入流,它“允許應用程序以與機器無關方式從底層輸入流中讀取基本 Java 數據類型”。
  6. PushbakInputStream:回退輸入流。java中讀取數據的方式是順序讀取,如果某個數據不需要讀取,需要程序處理。PushBackInputStream就可以將某些不需要的數據回退到緩沖中。
  7. ObjectInputStream:對象輸入流。用來提供對“基本數據或對象”的持久存儲。通俗點講,也就是能直接傳輸對象(反序列化中使用)。
  8. PipedInputStream:管道字節輸入流。它和PipedOutputStream一起使用,能實現多線程間的管道通信。
  9. SequenceInputStream:合並輸入流。依次將多個源合並成一個源。
  10. StringBufferInputStream:字符相關流。已經過時不多說。
  11. ByteArrayInputStream:字節數組輸入流,該類的功能就是從字節數組(byte[])中進行以字節為單位的讀取,也就是將資源文件都以字節的形式存入到該類中的字節數組中去,我們拿也是從這個字節數組中拿。

 

②、字節輸出流OutputStream

image

根據上圖介紹各個類的作用:

  1. OutputStream:字節輸出流基類,是所有的字節輸出流的父類,它是一個抽象類。
  2. FileOutputStream:文件輸出流。該類實現了一個輸出流,將數據輸出到文件。
  3. FilterOutputStream :過濾流。用來封裝其它的輸出流,並為它們提供額外的功能(序列化中使用)。它主要包括BufferedOutputStream, DataOutputStream和PrintStream。
  4. BufferedOutputStream:緩沖輸出流。給輸出流提供緩沖功能。
  5. DataOutputStream:是用來裝飾其它輸出流,將DataOutputStream和DataInputStream輸入流配合使用,“允許應用程序以與機器無關方式從底層輸入流中讀寫基本 Java 數據類型”。
  6. PrintStream:是用來裝飾其它輸出流。它能為其他輸出流添加了功能,使它們能夠方便地打印各種數據值表示形式。
  7. ObjectOutputStream:對象輸出流。該類將實現了序列化的對象序列化后寫入指定地方。 
  8. PipedOutputStream:管道字節輸出流。它和PipedInputStream一起使用,能實現多線程間的管道通信,是管道的發送端。
  9. ByteArrayOutputStream:字節數組輸出流。該類實現了一個輸出流,其數據被寫入由byte數組充當的緩沖區,緩沖區會隨着數據的不斷寫入而自動增長。

 

③、字符輸入流Reader

image

根據上圖介紹各個類的作用:

  1. Reader:是所有的輸入字符流的父類,它是一個抽象類。
  2. CharReader、StringReader 是兩種基本的介質流,它們分別將Char 數組、String中讀取數據。
  3. PipedReader 是從與其它線程共用的管道中讀取數據。
  4. BufferedReader是一個裝飾器,它和其子類LineNumberReader負責裝飾其它Reader對象。
  5. InputStreamReader:是一個連接字節流和字符流的橋梁,它將字節流轉變為字符流。FileReader 可以說是一個達到此功能、常用的工具類,在其源代碼中明顯使用了將FileInputStream 轉變為Reader 的方法。我們可以從這個類中得到一定的技巧。Reader 中各個類的用途和使用方法基本和InputStream 中的類使用一致。后面會有Reader 與InputStream 的對應關系。
  6. FilterReader 是所有自定義具體裝飾流的父類,其子類PushbackReader 對Reader對象進行裝飾,會增加一個行號。

 

④、字符輸出流Writer

image

根據上圖介紹各個類的作用:

  1. Writer:是所有的輸出字符流的父類,它是一個抽象類。
  2. CharArrayWriter、StringWriter 是兩種基本的介質流,它們分別向Char 數組、String 中寫入數據。PipedWriter 是向與其它線程共用的管道中寫入數據,
  3. BufferedWriter 是一個裝飾器為Writer 提供緩沖功能。
  4. PrintWriter 和PrintStream 極其類似,功能和使用也非常相似。
  5. OutputStreamWriter:是OutputStream 到Writer 轉換的橋梁,它的子類FileWriter 其實就是一個實現此功能的具體類(具體可以研究一SourceCode)。功能和使用和OutputStream 極其類似。

 

    如果博客對你有一點點幫助的話,哪怕只有一點點,能否動一下靚仔靚女的手指點個贊。
            


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM