1. 程式人生 > >java 位元組流入門(記憶體陣列流)

java 位元組流入門(記憶體陣列流)

導讀

上篇文章介紹了兩種常用的檔案輸入輸出流:

其中向檔案中寫入的資料都是預先定義好的位元組陣列 byte[] ,本文介紹另一種在記憶體中維護位元組陣列更常用的方式:記憶體陣列輸入輸出流。

ByteArrayOutputStream

記憶體陣列流,就是和記憶體中的陣列相關的一個流,可以將位元組陣列寫到輸出流中,也可以將位元組陣列從輸入流中讀出來,不涉及磁碟。記憶體陣列輸出流可以看成一個可自動擴容的 byte 陣列,可以往裡寫位元組。

預設初始化 32 個位元組的大小。最大容量是 2^31-9 個位元組(2G)。只要資料不超過2G,都可以往裡寫。每次寫資料之前,會先計算需要的容量大小,如果需要擴容,擴大到 max{原來的兩倍,需要的容量大小}

此外,還可以將 ByteArrayOutputStream 中的位元組陣列拿出來,拿出來的只是真實存在的資料量。

//為了驗證擴容方式,把其內部緩衝區拿出來
class MyByteArrayOutputStream extends ByteArrayOutputStream {

    public byte[] getBuf() {
        return super.buf;
    }
}

private static void outputStreamTest() throws IOException {

        // 預設緩衝區大小 32 位元組
        MyByteArrayOutputStream out
= new MyByteArrayOutputStream(); // 寫入 32 個位元組,此時 for(int i = 0; i < 32; i++) { out.write(1); } System.out.println("當前緩衝區長度:" + out.getBuf().length + " 當前資料長度:" + out.size()); // 寫入 1 個位元組,使所需容量為 33 個位元組,大於原來 32 位元組的容量 out.write(2); System.out
.println("當前緩衝區長度:" + out.getBuf().length + " 當前資料長度:" + out.size() + " 擴大到原來的兩倍了"); // 取出資料 byte[] ret = out.toByteArray(); print(ret); // 寫入新資料,使其空間正好比原空間的 2 倍大 3 個位元組 out.write(new byte[out.getBuf().length*2-out.size()+3]); System.out.println("當前緩衝區長度:" + out.getBuf().length + " 當前資料長度:" + out.size() + " 擴大到需要的容量大小了"); }

輸出:

當前緩衝區長度:32 當前資料長度:32
當前緩衝區長度:64 當前資料長度:33 擴大到原來的兩倍了
長度: 33 ,內容:111111111111111111111111111111112
當前緩衝區長度:131 當前資料長度:131 擴大到需要的容量大小了

ByteArrayInputStream

這個輸入流就是把一個位元組陣列 byte[] 包裝了一下,使其具有流的屬性,可順序讀下去。還可標記跳回來繼續讀。

private static void inputStreamTest() throws IOException {
        byte[] b1 = new byte[]{1,2,3,4};
        ByteArrayInputStream input = new ByteArrayInputStream(b1);

        System.out.println("剩餘位元組數: "+input.available());

        byte[] b2 = new byte[2];
        input.read(b2);
        print(b2);
        System.out.println("剩餘位元組數: " + input.available());

        input.read(b2);
        print(b2);
        System.out.println("剩餘位元組數: " + input.available() + " 沒得讀了");

        b2 = new byte[2];
        input.read(b2);
        print(b2);
    }

    private static void print(byte[] array) {
        System.out.print("長度: " + array.length + " ,內容:");
        for (byte b : array) {
            System.out.print(b);
        }
        System.out.println();
    }

輸出:

剩餘位元組數: 4
長度: 2 ,內容:12
剩餘位元組數: 2
長度: 2 ,內容:34
剩餘位元組數: 0 沒得讀了
長度: 2 ,內容:00

為什麼要用 ByteArrayInputStream 而不直接操作 byte 陣列?有以下幾種情況:

(1)其他介面需要一個 InputStream,而你只有一個 byte[],這時候必須包裝一下。

(2)希望以流的方式操作位元組陣列。

如果其他地方只需要一個 byte[],就沒必要包裝了,直接傳 byte[] 就好了。

這兩個流都是對記憶體中的資料進行操作,在需要動態維護一個位元組陣列時,可以使用 ByteArrayOutputStream,這個變數通常叫 baos 。另外,此次程式碼和上次程式碼都放在 github 上了,可以點閱讀原文,下邊這個也是:

歡迎關注個人公眾號:資料庫漫遊指南

這裡寫圖片描述