天天看點

Java IO - InputStream&OutputStream

基本概念

InpuStream/OuputStream(位元組輸入流/位元組輸出流),它們都是抽象類,并且都實作了 Closeable 接口,表示所有位元組(byte)輸入流(輸出流)的類。

源碼分析

1.InputStream

類結構如下

Java IO - InputStream&OutputStream

成員變量

// 成員常量,表示 skip(跳躍、丢棄)操作時能丢棄的最大數量
private static final int MAX_SKIP_BUFFER_SIZE = ;
           

構造函數,它有一個預設的無參造函數。

read 方法,定義了三個 read 方法,代表不同的讀取方式。

  • ① 是一個抽象方法,留給子類實作。
  • ② 通過調用 ③ 實作。
  • ③ 的實際操作依靠 ① 來完成。
// ①從輸入流中讀取資料的下一個位元組
public abstract int read() throws IOException;

// ②從輸入流中讀取一定數量的位元組,并将其存儲在緩沖區數組 b 中
public int read(byte b[]) throws IOException {
    return read(b, , b.length);
}

// ③将輸入流中最多 len 個資料位元組讀入 byte 數組
public int read(byte b[], int off, int len) throws IOException {

    // 校驗參數的合法性
    if (b == null) {
        throw new NullPointerException();
    } else if (off <  || len <  || len > b.length - off) {
        throw new IndexOutOfBoundsException();
    } else if (len == ) {
        return ;
    }

    // 先讀取一個位元組,用來判斷是否到流的末尾。若是,傳回 -1
    int c = read();
    if (c == -) {
        return -;
    }

    // 将上面讀取的一個位元組的值添加進數組
    b[off] = (byte) c;

    int i = ;

    // 繼續讀取流,直到 len 或 流末尾
    try {
        for (; i < len; i++) {
            // 實際通過 read 來進行操作
            c = read();
            if (c == -) {
                break;
            }
            // 位元組存放的位置從 off 開始
            b[off + i] = (byte) c;
        }
    } catch (IOException ee) {
    }
    return i;
}
           

skip 方法,它表示跳躍,丢棄操作。

它可以跳過(丢棄)指定數量的位元組,然後再繼續讀取流。

它實際上通過 read 方法來進行跳躍操作,然後建立了一個位元組數組用來儲存被丢棄的位元組。

public long skip(long n) throws IOException {

    long remaining = n;
    int nr;

    // 如果 n 為 0,表示不進行跳躍(丢棄)操作。
    if (n <= ) {
        // 關鍵 -->傳回值為 0 ,說明有 0 個位元組被丢棄
        return ;
    }

    // 最多隻能丢棄 2048 個位元組
    int size = (int) Math.min(MAX_SKIP_BUFFER_SIZE, remaining);

    // 建立數組用來儲存被丢棄的位元組
    byte[] skipBuffer = new byte[size];

    while (remaining > ) {
        // 關鍵 --> 通過 read 方法完成該操作
        nr = read(skipBuffer, , (int) Math.min(size, remaining));

        // 如果進行該操作時,提前到達流末尾,則不再繼續
        if (nr < ) {
            break;
        }

        // 表示剩餘需要丢棄位元組的數量
        remaining -= nr;
    }

    return n - remaining;
}
           

剩餘方法,大多沒有具體的實作,都留給子類做擴充,這裡先不細說。

// 傳回流中剩下可讀取的位元組數量,預設傳回 0
public int available() throws IOException {
    return ;
}

// 關閉流操作,空方法,留給子類實作
public void close() throws IOException {
}

// 标記操作,空方法,留給子類實作
public synchronized void mark(int readlimit) {
}

// 釋放标記,與 mark 配套使用
public synchronized void reset() throws IOException {
    throw new IOException("mark/reset not supported");
}

// 判斷是否支援标記,預設不支援
public boolean markSupported() {
    return false;
}
           

2.OutputStream

類結構如下

Java IO - InputStream&amp;OutputStream

構造函數,它有一個無參的構造函數

write 方法,同樣有三種寫入方式。

  • ① 是一個抽象方法,留給子類實作。
  • ② 通過調用 ③ 實作。
  • ③ 的實際操作依靠 ① 來完成。
// 将指定的位元組寫入此輸出流(抽象方法)
public abstract void write(int b) throws IOException;

// 将 b.length 個位元組從指定的 byte 數組寫入此輸出流
public void write(byte b[]) throws IOException {
    write(b, , b.length);
}

// 将指定 byte 數組中從偏移量 off 開始的 len 個位元組寫入此輸出流
public void write(byte b[], int off, int len) throws IOException {

    // 校驗參數的合法性
    if (b == null) {
        throw new NullPointerException();
    } else if ((off < ) || (off > b.length) || (len < ) || ((off + len) > b.length) || ((off + len) < )) {
        throw new IndexOutOfBoundsException();
    } else if (len == ) {
        return;
    }

    // 将數組中的所有位元組内容寫入流
    for (int i = ; i < len; i++) {
        write(b[off + i]);
    }
}
           

剩餘方法

//将緩存中流的内容強制輸出到目的地
public void flush() throws IOException {
}

public void close() throws IOException {
}
           

原了解釋

1. 按位元組讀取

假設下面代碼一段位元組流

Java IO - InputStream&amp;OutputStream

當位元組輸入流按位元組讀取時,即 read():

  • 讀取第一個位元組,傳回值1。
Java IO - InputStream&amp;OutputStream
  • 讀取第二個位元組,傳回值 2.
Java IO - InputStream&amp;OutputStream
  • 讀取到最後,發現已經到達流末尾了,傳回 -1。
Java IO - InputStream&amp;OutputStream

2.按位元組數組讀取

假設位元組數組的大小為 3,即 read(buffer,0,3):

  • 它會先讀取 1 個位元組用于判斷流是否達到末尾,并将值放入數組的第一個位置(n =0)。
Java IO - InputStream&amp;OutputStream
  • 然後按照循環(n<3)來讀取,并将值添加數組
Java IO - InputStream&amp;OutputStream

3.跳躍操作

假設現在跳躍的個數為 3。

Java IO - InputStream&amp;OutputStream

将丢棄的位元組添加進緩沖數組。

Java IO - InputStream&amp;OutputStream