什麼是Buffer?
Buffer即緩衝區的意思,緩衝區本質上是一個可以讀寫數據的內存塊,可以理解成是一個容器對象,該對象提供了一組方法,可以輕鬆的使用內存塊,緩衝區對象內置了一些機制,能夠跟蹤和記錄緩衝區的狀態變化情況;
Buffer類及子類
Buffer爲緩衝區的父類,以下是常用子類:
類名 | 描述 |
---|---|
ByteBuffer | 存儲字節數據 |
CharBuffer | 存儲字符數據 |
ShortBuffer | 存儲短整形數據 |
IntBuffer | 存儲短整型數據 |
LongBuffer | 存儲長整型數據 |
DoubleBuffer | 存儲雙精度浮點數據 |
FloatBuffer | 存儲單精度浮點數據 |
Buffer類定義的所有的緩衝區都具有四個屬性來提供其存儲的元素信息:
屬性名 | 描述 |
---|---|
mark | 標記 |
position | 操作緩衝區的位置,下一個要被讀或寫的元素的索引,每次讀寫緩衝區數據時都會改變此值,爲下次讀寫做準備 |
limit | 表示緩衝區的當前終點,不能對緩衝區超過極限的位置進行讀寫操作,但極限是可以修改的 |
capacity | 容量,即可以容納的最大數據量,在緩衝區創建時被設定並且不能改變 |
Buffer類常用方法列表:
方法名 | 描述 | jdk版本 |
---|---|---|
public final int capacity() | 返回此緩衝區的容量 | 1.4 |
public final int position() | 返回此緩衝區的位置 | 1.4 |
public final Buffer position (int newPositio) | 設置此緩衝區的位置 | 1.4 |
public final int limit() | 返回此緩衝區的限制 | 1.4 |
public final Buffer limit (int newLimit) | 設置此緩衝區的限制 | 1.4 |
public final Buffer mark() | 在此緩衝區的位置設置標記 | 1.4 |
public final Buffer reset() | 將此緩衝區的位置重置爲以前標記的位置 | 1.4 |
public final Buffer clear() | 清除此緩衝區, 即將各個標記恢復到初始狀態,但是數據並沒有真正擦除, 後面操作會覆蓋 | 1.4 |
public final Buffer flip() | 反轉此緩衝區 | 1.4 |
public final Buffer rewind() | 重繞此緩衝區 | 1.4 |
public final int remaining() | 返回當前位置與限制之間的元素數 | 1.4 |
public final boolean hasRemaining() | 告知在當前位置和限制之間是否有元素 | 1.4 |
public abstract boolean isReadOnly() | 告知此緩衝區是否爲只讀緩衝區 | 1.4 |
public abstract boolean hasArray() | 告知此緩衝區是否具有可訪問的底層實現數組 | 1.6 |
public abstract Object array() | 返回此緩衝區的底層實現數組 | 1.6 |
public abstract int arrayOffset() | 返回此緩衝區的底層實現數組中第一個緩衝區元素的偏移量 | 1.6 |
public abstract boolean isDirect() | 告知此緩衝區是否爲直接緩衝區 | 1.6 |
從前面可以看出對於 Java 中的基本數據類型(boolean除外),都有一個Buffer類型與之相對應,最常用的自然是ByteBuffer類(二進制數據),該類的主要方法如下:
方法名 | 描述 |
---|---|
public static ByteBuffer allocateDirect(int capacity) | 創建直接緩衝區 |
public static ByteBuffer allocate(int capacity) | 設置緩衝區的初始容量 |
public static ByteBuffer wrap(byte[] array) | 把一個數組放到緩衝區中使用 |
public static ByteBuffer wrap(byte[] array,int offset, int length) | 構造初始化位置offset和上界length的緩衝區 |
public abstract byte get() | 從當前位置position上get,get之後,position會自動+1 |
public abstract byte get (int index) | 從絕對位置get |
public abstract ByteBuffer put (byte b) | 從當前位置上添加,put之後,position會自動+1 |
public abstract ByteBuffer put (int index, byte b) | 從絕對位置上put |
Buffer使用示例
public class BasicBuffer {
public static void main(String[] args) {
// 創建一個大小爲10的int類型的buffer
IntBuffer intBuffer = IntBuffer.allocate(10);
// 向buffer中存放數據
for (int i = 0; i < 10; i++) {
intBuffer.put(i);
}
// 讀取buffer之前需要進行反轉
intBuffer.flip();
// 遍歷buffer,讀取buffer數據
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
}
}
}
Buffer使用注意事項
- ByteBuffer支持類型化的put和get,put放入的是什麼類型,get就應該使用相應的數據類型來取出,否則可能出現BufferUnderflowException異常,如下代碼所示:
public class ByteBufferPutGet {
public static void main(String[] args) {
// 創建一個buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
byteBuffer.putChar('陳');
byteBuffer.putInt(1);
byteBuffer.putShort((short) 9);
// 反轉
byteBuffer.flip();
// System.out.println(byteBuffer.getLong());
System.out.println(byteBuffer.getChar());
System.out.println(byteBuffer.getInt());
System.out.println(byteBuffer.getShort());
}
}
- 普通buffer設置爲只讀buffer,如果往只讀buffer裏面添加數據則會拋出ReadOnlyBufferException,如下代碼所示:
public class ReadOnlyBuffer {
public static void main(String[] args) {
IntBuffer intBuffer = IntBuffer.allocate(8);
for (int i = 0; i < 8; i++) {
intBuffer.put(i);
}
// 反轉
intBuffer.flip();
// 得到一個只讀的buffer
IntBuffer readOnlyBuffer = intBuffer.asReadOnlyBuffer();
System.out.println("readOnlyBuffferClass:"+readOnlyBuffer.getClass());
while (readOnlyBuffer.hasRemaining()) {
System.out.println(readOnlyBuffer.get());
}
readOnlyBuffer.put(99); // 此處會拋出ReadOnlyBufferException
}
}