Java NIO 三大元件之 Buffer
阿新 • • 發佈:2019-12-03
NIO大三元件 之Buffer
一、什麼是Buffer
Buffer是用於特定原始型別的資料的容器。 它的實質就是一組陣列,用於儲存不同型別的資料。
二、緩衝區的型別
緩衝區型別除了Boolean值型別外,其餘基本型別都含有。
NIO中定義的抽象緩衝區物件如下(均繼承至Buffer抽象類):
- ByteBuffer
- CharBuffer
- ShortBuffer
- IntBuffer
- LongBuffer
- FloatBuffer
- DoubleBuffer
上述類均為抽象類,它們的實現還分有直接緩衝區和非直接緩衝區。
三、緩衝區中的四個核心屬性
- category: 容量,表示緩衝區的大小,一旦宣告就不可改變。
- limit: 界限,表示緩衝區中可以操作資料的大小。(llimit後面的資料不可讀寫)
- position: 位置,表示緩衝區中正在操作資料的位置。
- mark: 標記,可以標記當前position的位置。
寫操作
進行寫操作時,limit=category,limit
表示的是可以寫的地址範圍。
而position
則表示當前寫的索引,每寫一個位元組position則+1。
讀操作
進行讀操作時,limit=position,limit
此時則表示可讀取的範圍,此時範圍則會被賦值為寫的position
。
而當position
賦值完給limit
後,position
則置零。在讀操作中position
則表示讀的索引。
它們之間的關係
mark <= position <= limit <= capacity
@Test public void markTest(){ String str = "abcde"; ByteBuffer buf = ByteBuffer.allocate(1024); byte[] bytes = new byte[10]; buf.put(str.getBytes()); //切換到讀模式 buf.flip(); //獲取buf的兩個位元組 buf.get(bytes, 0, 2); System.out.println(new String(bytes)); //標記position的位置 buf.mark(); //獲取buf的兩個位元組 buf.get(bytes, 2, 2); System.out.println(new String(bytes)); System.out.println(buf.position()); //回到position=2的位置 buf.reset(); System.out.println(buf.position()); }
四、存取緩衝區資料的核心方法
- put():存入資料到緩衝區中
- get(): 獲取緩衝區中的資料
- flip(): 讀寫切換
- clear():清空寫快取,,只是把position和limit重置為最初狀態,但是快取區的內容並沒有刪除
- mark(): 儲存當前position的位置
- reset(): 把當前的position重置為mark的值
- rewind(): 重讀操作,position置0
@Test
public void bufferMethodTest(){
String str = "abcde";
//宣告一個Byte緩衝區(非直接緩衝區),並設定緩衝區大小為1024
ByteBuffer buf = ByteBuffer.allocate(1024);
//直接緩衝區申請方式
//ByteBuffer.allocateDirect(1024);
System.out.println("-------------------------allocate------------------------");
//0
System.out.println(buf.position());
//1024
System.out.println(buf.limit());
//1024
System.out.println(buf.capacity());
System.out.println("-------------------------put------------------------");
//把str的資料放入緩衝區
buf.put(str.getBytes());
//5
System.out.println(buf.position());
//1024
System.out.println(buf.limit());
//1024
System.out.println(buf.capacity());
//3.切換讀取資料模式
buf.flip();
System.out.println("-------------------------get------------------------");
byte[] bytes = new byte[20];
//讀取緩衝區理的5個位元組
buf.get(bytes,0, buf.limit());
//5,表示資料讀到的位置
System.out.println(buf.position());
//5.表示可以讀的位置
System.out.println(buf.limit());
System.out.println(buf.capacity());
//5. rewind: 可重讀
buf.rewind();
System.out.println("-------------------------rewind------------------------");
//position回到0
System.out.println(buf.position());
//5.表示可以讀的位置,5
System.out.println(buf.limit());
System.out.println(buf.capacity());
//clear(): 清空快取區,但資料任然存在,只是把position和limit重置為最初狀態。
buf.clear();
System.out.println("-------------------------clear------------------------");
//postion變為0
System.out.println(buf.position());
//1024
System.out.println(buf.limit());
System.out.println(buf.capacity());
}
五、補充
關於直接緩衝區與非直接緩衝區
- 直接緩衝區: 緩衝區地址直接對映到磁碟地址。
- 非直接緩衝區: 緩衝區地址先通過JVM快取,然後再由JVM向OS申請記憶體空間。(實質是堆)
兩種方式的優缺點
- 非直接緩衝區有JVM到OS這段中間開銷,使得訪問效能下降。但是由於快取在JVM堆中,資料受程式控制。
- 直接緩衝區沒有中間開銷,但由於記憶體是向OS申請,緩衝區的資料儲存不受程式的控制。