Java 中的“流”是一種抽象的概念,也是一種比喻,就好比水流一樣,水流是從一端流向另一端的,而在 Java 中的“水流”就是數據,數據會從一端“流向”另一端。
根據流的方向性,我們可以將流分為輸入流和輸出流,當程序需要從數據源中讀入數據的時候就會開啟一個輸入流,相反,寫出數據到某個數據源目的地的時候也會開啟一個輸出流,數據源可以是文件、內存或者網絡等。
1.什么是字節流?
字節流的基本單位為字節(Byte),一個字節通常為 8 位,它是用來處理二進制(數據)的。字節流有兩個基類:InputStream
(輸入字節流)和 OutputStream
(輸出字節流)。
常用字節流的繼承關系圖如下圖所示:
其中 InputStream
用於讀操作,而 OutputStream
用於寫操作。
2.什么是字符流
字符 流的基本單位為 Unicode,大小為兩個字節(Byte),它通常用來處理文本數據。字符流的兩個基類:Reader
(輸入字符流)和 Writer
(輸出字符流)。
3.流的分類
流可以根據不同的維度進行分類,比如可以根據流的方向進行分類,也可以根據傳輸的單位進行分類,還可以根據流的功能進行分類,比如以下幾個。
① 按流向分類
- 輸出流:
OutputStream
和Writer
為基類。 - 輸入流:
InputStream
和Reader
為基類
② 根據傳輸數據單位分類
- 字節流:
OutputStream
和InputStream
為基類。 - 字符流:
Writer
和Reader
為基類。
③ 根據功能分類
- 字節流:可以從或向一個特定的地方(節點)讀寫數據。
- 處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調用實現數據讀寫。
PS:我們通常是以傳輸數據的單位來為流進行分類。
4.寫文件的6種方法
寫入文件的方法主要源於字符流 Writer
和輸出字節流 OutputStream
的子類,如下圖所示:
以上標注✅號的類就是用來實現文件寫入的類,除此之外,在 JDK 1.7 中還提供了 Files
類用來實現對文件的各種操作,接下來我們分別來看。
方法 1:FileWriter
FileWriter
屬於「字符流」體系中的一員,也是文件寫入的基礎類,它包含 5 個構造函數,可以傳遞一個具體的文件位置,或者 File
對象,第二參數表示是否要追加文件,默認值為 false
表示重寫文件內容,而非追加文件內容(關於如何追加文件,我們后面會講)。
方法 2:BufferedWriter
BufferedWriter
也屬於字符流體系的一員,與 FileWriter
不同的是 BufferedWriter
自帶緩沖區,因此它寫入文件的性能更高
小知識點:緩沖區
緩沖區又稱為緩存,它是內存空間的一部分。也就是說,在內存空間中預留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數據,這部分預留的空間就叫做緩沖區。
緩沖區的優勢以文件流的寫入為例,如果我們不使用緩沖區,那么每次寫操作 CPU 都會和低速存儲設備也就是磁盤進行交互,那么整個寫入文件的速度就會受制於低速的存儲設備(磁盤)。但如果使用緩沖區的話,每次寫操作會先將數據保存在高速緩沖區內存上,當緩沖區的數據到達某個閾值之后,再將文件一次性寫入到磁盤上。因為內存的寫入速度遠遠大於磁盤的寫入速度,所以當有了緩沖區之后,文件的寫入速度就被大大提升了。
方法 3:PrintWriter
無論是 PrintWriter
還是 BufferedWriter
都必須基於 FileWriter
類來完成調用。
方法 4:FileOutputStream
方法 5:BufferedOutputStream
BufferedOutputStream
屬於字節流體系中的一員,與 FileOutputStream
不同的是,它自帶了緩沖區的功能,因此性能更好,它的實現代碼如下:
方法 6:Files
接下來的操作方法和之前的代碼都不同,接下來咱們就使用 JDK 7 中提供的一個新的文件操作類 Files
來實現文件的寫入。
Files
類是 JDK 7 添加的新的操作文件的類,它提供了提供了大量處理文件的方法,例如文件復制、讀取、寫入,獲取文件屬性、快捷遍歷文件目錄等,這些方法極大的方便了文件的操作