天天看點

I/O流之位元組流的讀寫——Java進階知識講義系列(九)

作者:老K玩代碼

歡迎來到全網最完整的Java進階知識系列教程!!!每天定時更新!!!

本期的課程,我們繼續分享I/O檔案讀寫。

IO檔案讀寫,根據資料格式不同,分為位元組流讀寫和字元流讀寫,我們今天先講位元組流讀寫。

如果你正在學習Java,不妨收藏這篇文章,或者關注我,定期收獲與Java有關的知識和項目資訊!

I/O流之位元組流的讀寫——Java進階知識講義系列(九)

之前八課的内容,可點選下方擷取:

老K玩代碼:如何優雅的處理異常--Java進階知識講義系列(一)

老K玩代碼:包裝器類裝箱與拆箱的藝術——Java進階知識講義系列(二)

老K玩代碼:一文講透Java字元串——Java進階知識講義系列(三)

老K玩代碼:List的用法和執行個體詳解——Java進階知識講義系列(四)

老K玩代碼:Set的用法和執行個體詳解——Java進階知識講義系列(五)

老K玩代碼:Map的用法和執行個體詳解——Java進階知識講義系列(六)

老K玩代碼:常用集合的排序方法——Java進階知識講義系列(七)

老K玩代碼:I/O流之File類的用法和執行個體詳解——Java進階知識講義系列(八)

I/O流之位元組流的讀寫——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一個贊哦,你的支援是我持續輸出課程内容最大的動力!

I/O流之位元組流的讀寫——Java進階知識講義系列(九)

結束語

我是專注于開發領域的 @老K玩代碼,會持續生産關于如何學習程式設計語言的優質内容。

如果你想學習Java程式設計,或者想精進你的Java程式設計能力,可以關注我。

如果你對開發、程式設計有任何疑問或者有想了解的内容,而我暫時沒有寫到的,也歡迎随時來找我聊聊。

I/O流之位元組流的讀寫——Java進階知識講義系列(九)

繼續閱讀