序
歡迎來到全網最完整的Java進階知識系列教程!!!每天定時更新!!!
本期的課程,我們繼續分享I/O檔案讀寫。
IO檔案讀寫,根據資料格式不同,分為位元組流讀寫和字元流讀寫,我們今天先講位元組流讀寫。
如果你正在學習Java,不妨收藏這篇文章,或者關注我,定期收獲與Java有關的知識和項目資訊!
之前八課的内容,可點選下方擷取:
老K玩代碼:如何優雅的處理異常--Java進階知識講義系列(一)
老K玩代碼:包裝器類裝箱與拆箱的藝術——Java進階知識講義系列(二)
老K玩代碼:一文講透Java字元串——Java進階知識講義系列(三)
老K玩代碼:List的用法和執行個體詳解——Java進階知識講義系列(四)
老K玩代碼:Set的用法和執行個體詳解——Java進階知識講義系列(五)
老K玩代碼:Map的用法和執行個體詳解——Java進階知識講義系列(六)
老K玩代碼:常用集合的排序方法——Java進階知識講義系列(七)
老K玩代碼:I/O流之File類的用法和執行個體詳解——Java進階知識講義系列(八)
接下來就讓我們正式開始分享課程内容吧。
一、InputStream類
1. 概念
IO類可以分成四個大類:
. | 輸入 | 輸出 |
位元組流(常見場景:圖檔) | InputStream | OutputStream |
字元流(常見場景:文檔) | Reader | Writer |
其中,InputStream類是一個位元組流輸入的抽象類,常見的子類有:FileInputStream、BufferedInputStream、ObjectInputStream等。
2. 輸入位元組流-代碼實作
輸入位元組流的代碼實作一般分為三步:
- 對象執行個體化
- 讀取檔案
- 關閉檔案
代碼示例(代碼初構):
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IODemo {
public static void main(String[] args) throws IOException {
// ① 對象執行個體化
File f = new File("io.jpg"); // 擷取檔案
InputStream fis = new FileInputStream(f); // 利用FileInputStream對象讀取檔案
// ②讀取檔案
byte[] b = new byte[1024]; // 用來收容讀取結果的位元組容器
int len; // 用來記錄每次讀取的資料位元組數
while ((len = fis.read(b)) != -1) {
System.out.println(len);
}
// ③關閉檔案
fis.close();
}
}
說明:
- 這裡的FileInputStream是InputStream的子類;
- (len = fis.read(b)) != -1是一種特别的表達式,分為兩步: ①将fis.read(b)的傳回值儲存到len變量中; ②判斷重新複制後的len是否為-1。
可以看到,上例這段代碼會有IOException異常,為了便于初學者了解,目前我們不對異常處理,而是向上抛出。但這個方法我們并不推薦,建議使用try...catch...finally...語句将異常捕獲,具體如下:
代碼示例(完整代碼):
import java.io.*;
public class IODemo {
public static void main(String[] args) {
// ① 對象執行個體化
File f = new File("io.jpg");
InputStream fis = null;
// ②讀取檔案
try {
fis = new FileInputStream(f);
byte[] b = new byte[1024];
int len;
while((len = fis.read(b)) != -1) {
System.out.println(len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
// ③關閉檔案
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
說明:
- 在建立FileInputStream執行個體的時候,可能會抛出FileNotFoundException異常,我們用try...catch...捕獲;
- 在fis.read(b)的時候,可能會抛出IOException異常,我們用try...catch...捕獲;
- 由于上述兩個異常可以寫在同一個代碼塊,且FileNotFoundException是IOException的子類,我們可以直接用IOException一次性捕獲上述兩種異常情況;
- 不論檔案讀寫是否成功,我們都需要在最後把FileInputStream執行個體close掉,是以把這段邏輯寫在finally代碼塊中;
- fis.close也可能存在IOException,通過try..catch...捕獲;
- 為避免fis在finally代碼塊中出現空指針異常(NullPointerException),我們在try...catch...語句外先對fis變量進行聲明。
二、OutputStream類
1. 概念
OutputStream類與InputStream類相對應,是一個位元組流輸出的抽象類,常見的子類有:FileOutputStream、BufferedOutputStream、ObjectOutputStream等;
2. 輸出位元組流-代碼實作
示例代碼(代碼初構)
import java.io.*;
public class IODemo {
public static void main(String[] args) throws IOException {
// ① 對象執行個體化
File f1 = new File("io1.jpg");
File f2 = new File("io2.jpg");
// ②讀寫檔案
InputStream fis = new FileInputStream(f1);
OutputStream fos = new FileOutputStream(f2);
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
System.out.println(len);
fos.write(b);
}
// ③關閉檔案
fos.close();
fis.close();
}
}
說明:
- 上例實作的是建立io1.jpg圖檔的副本io2.jpg,同學可以在目前目錄下準備一張名為io1.jpg的圖檔
上例為清晰展示流程和步驟,将異常向上抛出,在實際工作中并不推薦這種寫法,實踐中建議用try...catch...方法捕獲異常。
詳見下例:
代碼示例(完整代碼)
import java.io.*;
public class IODemo {
public static void main(String[] args) {
// ① 對象執行個體化
File f1 = new File("io1.jpg");
File f2 = new File("io2.jpg");
InputStream fis = null;
OutputStream fos = null;
// ②讀寫檔案
try {
fis = new FileInputStream(f1);
fos = new FileOutputStream(f2);
byte[] b = new byte[1024];
int len;
while((len = fis.read(b)) != -1) {
System.out.println(len);
fos.write(b);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
// ③關閉檔案
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
說明:
- 這裡秉承着“先開後關”的程式設計邏輯,建議先開始讀寫的fis最後關閉close。
以上是Java進階知識系列第九講,關于位元組流讀寫的全部内容。
内容不多,和老K一起每天積累一點點,輕輕松松掌握Java知識。
正在學習的小夥伴記得給老K一個贊哦,你的支援是我持續輸出課程内容最大的動力!
結束語
我是專注于開發領域的 @老K玩代碼,會持續生産關于如何學習程式設計語言的優質内容。
如果你想學習Java程式設計,或者想精進你的Java程式設計能力,可以關注我。
如果你對開發、程式設計有任何疑問或者有想了解的内容,而我暫時沒有寫到的,也歡迎随時來找我聊聊。