緩沖區(Buffer)
1. 緩沖區(Buffer):一個用於特定基本數據類 型的容器。
由 java.nio 包定義的,所有緩沖區 都是 Buffer 抽象類的子類。
2. Java NIO 中的 Buffer 主要用於與 NIO 通道進行 交互,數據是從通道讀入緩沖區,從緩沖區寫入通道中的
3. Buffer 就像一個數組,可以保存多個相同類型的數據。
根 據數據類型不同(boolean 除外) ,有以下 Buffer 常用子類:
① ByteBuffer
② CharBuffer
③ ShortBuffer
④ IntBuffer
⑤ LongBuffer
⑥ FloatBuffer
⑦ DoubleBuffer
上述 Buffer 類 他們都采用相似的方法進行管理數據,
只是各自 管理的數據類型不同而已。都是通過如下方法獲取一個 Buffer 對象:
static XxxBuffer allocate(int capacity) : 創建一個容量為capacity 的 XxxBuffer 對象
4.Buffer 的常用方法
5.緩沖區的數據操作
Buffer 所有子類提供了兩個用於數據操作的方法:get() 與 put() 方法
① 獲取 Buffer 中的數據
get() :讀取單個字節
get(byte[] dst):批量讀取多個字節到 dst 中
get(int index):讀取指定索引位置的字節(不會移動 position)
② 放入數據到 Buffer 中
put(byte b):將給定單個字節寫入緩沖區的當前位置
put(byte[] src):將 src 中的字節寫入緩沖區的當前位置
put(int index, byte b):將指定字節寫入緩沖區的索引位置(不會移動 position)
6.直接與非直接緩沖區
① 字節緩沖區要么是直接的,要么是非直接的。
如果為直接字節緩沖區,則 Java 虛擬機會盡最大努力直接在 此緩沖區上執行本機 I/O 操作。
也就是說,在每次調用基礎操作系統的一個本機 I/O 操作之前(或之后),
虛擬機都會盡量避免將緩沖區的內容復制到中間緩沖區中(或從中間緩沖區中復制內容)。
② 直接字節緩沖區可以通過調用此類的 allocateDirect() 工廠方法來創建。
此方法返回的緩沖區進行分配和取消 分配所需成本通常高於非直接緩沖區。
直接緩沖區的內容可以駐留在常規的垃圾回收堆之外,
因此,它們對 應用程序的內存需求量造成的影響可能並不明顯。
所以,建議將直接緩沖區主要分配給那些易受基礎系統的 本機 I/O 操作影響的大型、持久的緩沖區。
一般情況下,最好僅在直接緩沖區能在程序性能方面帶來明顯好 處時分配它們。
③ 直接字節緩沖區還可以通過FileChannel 的 map() 方法 將文件區域直接映射到內存中來創建。
該方法返回 MappedByteBuffer 。Java 平台的實現有助於通過 JNI 從本機代碼創建直接字節緩沖區。
如果以上這些緩沖區 中的某個緩沖區實例指的是不可訪問的內存區域,
則試圖訪問該區域不會更改該緩沖區的內容,並且將會在 訪問期間或稍后的某個時間導致拋出不確定的異常。
④ 字節緩沖區是直接緩沖區還是非直接緩沖區可通過調用其 isDirect() 方法來確定。
提供此方法是為了能夠在 性能關鍵型代碼中執行顯式緩沖區管理
TestBuffer
package com.aff.nio; import java.nio.ByteBuffer; import org.junit.Test; /* * 緩沖區(buffer):在java NIO中負責存儲數據,緩沖區就是數組。用於存儲不同數據類型的數據的 * 根據數據類型不同(boolean除外), 提供了響應類型的緩沖區: * ByteBuffer * IntBuffer * ShortBuffer * CharBuffer * LongBuffer * FloatBuffer * DoubleBuffer * 上述緩沖區的管理方式幾乎一致, 通過 allocate() 獲取緩存區 * * * 2.緩沖區存儲數據的兩個核心方法 * put():存入數據到緩沖區中 * get():獲取緩緩區中的數據 * * 3.緩沖區中的四個核心屬性: * capacity:容量,表示緩沖區中最大存儲數據的容量,一旦聲明不能改變 * limit: 界限,表示緩沖區可以操作數據的大小(limit后的數據不能進行讀寫) * position:位置 表示緩沖區中正在操作數據的位置 * * mark:標記,表示記錄當前position的位置,可以通過reset()恢復到mark的位置 * 0<=mark<position<=limit<=capacity * *3.直接緩沖區與非直接緩沖區:
非直接緩沖區:通過allocate()方分配緩沖區,將緩沖區建立在JVM的內存中
非直接緩沖區:通過allocateDirect()方法分配直接緩沖區,將緩沖區建立在物理內存中,可以提高效率 */ public class TestBuffer { @Test public void test1() { String str = "abcdl"; // 1. 分配一個指定大小的緩沖區 ByteBuffer buf = ByteBuffer.allocate(1024); System.out.println("--------allocate()----------"); System.out.println(buf.capacity());//1024 System.out.println(buf.limit());//1024 System.out.println(buf.position());//0 // 2.put 方法存入數據到緩沖區 buf.put(str.getBytes()); System.out.println("--------put()----------"); System.out.println(buf.capacity());//1024 System.out.println(buf.limit());//1024 System.out.println(buf.position());//5 // 切換到讀取模式 buf.flip(); System.out.println("--------flip 讀取模式----------"); System.out.println(buf.capacity());//1024 System.out.println(buf.limit());//5 System.out.println(buf.position());//0; // 用get()方法讀取緩沖區中的數據 byte[] dst = new byte[buf.limit()]; buf.get(dst); System.out.println(new String(dst, 0, dst.length)); System.out.println("--------get()后----------"); System.out.println(buf.capacity());//1024 System.out.println(buf.limit());//5 System.out.println(buf.position());//5; // rewind() 可重復讀 buf.rewind(); System.out.println("--------rewind()----------"); System.out.println(buf.capacity());//1024 System.out.println(buf.limit());//5 System.out.println(buf.position());//0 // clear() 清空緩沖區,但是緩沖區的數據依然存在,但是處於被遺忘狀態 } }