java.io包中的 ByteArrayInputStream 類可用於讀取輸入數組(字節)。
要創建字節數組輸入流,我們必須首先導入java.io.ByteArrayInputStream包。導入包後,我們有兩個構造函數可用於創建輸入流:
ByteArrayInputStream input = new ByteArrayInputStream(arr);
ByteArrayInputStream input = new ByteArrayInputStream(arr, 2, 2);
類裡面有4個字段:
// Byte array provided by the creator of the stream
protected byte buf[];
// Index of the next character to read from the input stream's buffer
protected int pos;
// Current marked position in the stream
protected int mark = 0;
// Index is one greater than the last valid character in the input stream's buffer
protected int count;
這是我們的構造函數:
public ByteArrayInputStream(byte buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
public ByteArrayInputStream(byte buf[], int offset, int length) {
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.mark = offset;
}
ByteArrayInputStream 類的方法
方法 | 行動 |
---|---|
內部讀取() | 從此輸入流中讀取下一個字節的數據。 |
int read(byte b[], int off, int len) | 從輸入流中讀取幾個字節並將它們存儲在緩衝區數組b中。 off是目標數組b的偏移量。 len是要讀取的最大字節數。 |
長跳過(長n) | 跳過此輸入流中的 n 個字節的輸入。返回跳過的字節數(如果我們到達輸入流的末尾,它可能小於 n)。 |
內部可用() | 返回可以從此輸入流中讀取(或跳過)的剩餘字節數。 |
無效重置() | 將緩衝區重置為標記位置。標記的位置為 0,除非標記了另一個位置或在構造函數中指定了不同的偏移量。 |
布爾標記支持() | 檢查此InputStream是否支持標記/重置。為ByteArrayInputStream返回true。 |
無效關閉() | 什麼都不做。 |
無效標記(int readAheadLimit) | 設置標記等於當前位置的字段。如果調用了reset方法,那麼後續的讀取將從該位置開始。readAheadLimit參數未使用且不影響該方法的行為。 |
讓我們仔細看看這些方法,看看它們在實踐中是如何工作的。
讀()
當您想像從普通InputStream讀取字節一樣從ByteArrayInputStream讀取字節時,可以使用read()方法。
public static void main(String[] args) {
byte[] array = {1, 2, 3, 4};
try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
for (int i = 0; i < array.length; i++) {
int data = input.read();
System.out.print(data + ", ");
}
} catch (IOException e) {
e.printStackTrace();
}
}
可用的()
如果你想檢查你的緩衝區中是否有東西,你可以調用available()方法。
public static void main(String[] args) {
byte[] array = {1, 2, 3, 4};
try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
System.out.println("Bytes available for reading: " + input.available());
input.read();
System.out.println("Bytes available for reading " + input.available());
input.read();
System.out.println("Bytes available for reading " + input.available());
} catch (IOException e) {
e.printStackTrace();
}
}
我們將看到每次從緩衝區讀取後可用於讀取的字節數都會發生變化。
輸出:
可供讀取的字節數:3
可供讀取的字節數:2
跳過(長n)
您可以使用skip()方法跳過一定數量的字節而不讀取它們。
public static void main(String[] args) {
byte[] array = {1, 2, 3, 4};
try (ByteArrayInputStream input = new ByteArrayInputStream(array)) {
input.skip(2);
while (input.available() != 0) {
int data = input.read();
System.out.print(data + ", ");
}
} catch (IOException e) {
e.printStackTrace();
}
}
輸出:
重置()
此方法將緩衝流的位置重置為最後標記的位置。除非設置不同的標記,否則它是位置 0。
public static void main(String[] args) {
byte[] buf = {65, 66, 67, 68, 69};
try (ByteArrayInputStream input = new ByteArrayInputStream(buf)) {
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
System.out.println("Calling reset() method");
input.reset();
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
} catch (IOException e) {
e.printStackTrace();
}
}
我們將看到調用reset()方法會將我們帶到流的起點。
輸出:
讀取:66
讀取:67
讀取:68
調用 reset() 方法
讀取:65
讀取:66
標記(int readAheadLimit)
ByteArrayInputStream類的mark ()方法在當前字節位置設置內部標記,即緊接在先前讀取的字節之後。此方法採用一個參數,該參數指示在流變為無效之前標記之後可以讀取多少字節。默認情況下,如果未顯式設置標記,則ByteArrayInputStream會標記位置 0 或傳遞給其構造函數的偏移量的位置。重要的是要注意readAheadLimit標記與此類無關。
/* Note: For this class, {@code readAheadLimit}
* has no meaning.
*
* @since 1.1
*/
public void mark(int readAheadLimit) {
mark = pos;
}
下面是使用mark()和reset()方法在ByteArrayInputStream中設置標記的示例。我們將在前面的示例中添加對mark()方法的調用:
public static void main(String[] args) {
byte[] buf = {65, 66, 67, 68, 69};
try (ByteArrayInputStream input = new ByteArrayInputStream(buf)) {
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
input.mark(5);
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
System.out.println("Calling reset() method");
input.reset();
System.out.println("Read: " + input.read());
System.out.println("Read: " + input.read());
} catch (IOException e) {
e.printStackTrace();
}
}
我們可以看到當前流的位置發生了變化。
輸出:
讀取:66
讀取:67
讀取:68
讀取:69
調用 reset() 方法
讀取:68
讀取:69
標記支持()
markSupported ()方法讓您檢查是否可以設置標記。要了解返回值的來源,讓我們轉到方法的代碼:
/**
* Tests if this {@code InputStream} supports mark/reset. The
* {@code markSupported} method of {@code ByteArrayInputStream}
* always returns {@code true}.
*
* @since 1.1
*/
public boolean markSupported() {
return true;
}
該方法始終返回true。讓我們在實踐中對此進行測試。
public static void main(String[] args) {
byte[] buf = {65, 66, 67, 68, 69};
try (ByteArrayInputStream bais = new ByteArrayInputStream(buf)) {
boolean isMarkSupported = bais.markSupported();
System.out.println("isMarkSupported: " + isMarkSupported);
System.out.println("Read: " + bais.read());
System.out.println("Read: " + bais.read());
bais.mark(1);
System.out.println("Read: " + bais.read());
isMarkSupported = bais.markSupported();
System.out.println("isMarkSupported: " + isMarkSupported);
bais.reset();
isMarkSupported = bais.markSupported();
System.out.println("isMarkSupported: " + isMarkSupported);
} catch (IOException e) {
e.printStackTrace();
}
}
在執行了mark()和reset()方法之後,我們的流總是準備就緒並支持標記:
輸出:
讀取:65
讀取:66
讀取:67
isMarkSupported:true
isMarkSupported:true
關閉()
為了理解close方法,讓我們也看一下它的內部:
/**
* Closing a {@code ByteArrayInputStream} has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an {@code IOException}.
*/
public void close() throws IOException {
}
close 方法的文檔告訴我們關閉 ByteArrayInputStream沒有任何效果。可以在流關閉後調用ByteArrayInputStream類方法而不拋出IOException。
我們能得出什麼結論?
當我們想從字節數組中讀取數據時,我們需要一個ByteArrayInputStream 。將此類與知道如何使用InputStreams的其他代碼結合使用而不是單獨使用此類通常是有意義的。
GO TO FULL VERSION