Java NIO中的Buffer用於和NIO通道進行交互。如你所知,數據是從通道讀入緩衝區,從緩衝區寫入到通道中的。
緩衝區本質上是一塊可以寫入數據,然後可以從中讀取數據的內存。這塊內存被包裝成NIO Buffer對象,並提供了一組方法,用來方便的訪問該塊內存。
NIO中的關鍵Buffer實現有:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer,分別對應基本數據類型: byte, char, double, float, int, long, short。當然NIO中還有MappedByteBuffer, HeapByteBuffer, DirectByteBuffer等這裏先不進行陳述。
首先我們先創建一個Buffer
//create buffer with capacity of 11bytes
ByteBuffer buf = ByteBuffer.allocate(11);
可以把Buffer簡單地理解爲一組基本數據類型的元素列表,它通過幾個變量來保存這個數據的當前位置狀態:
索引 | 說明 |
---|---|
capacity | 緩衝區數組的總長度 |
position | 下一個要操作的數據元素的位置 |
limit | 所有對Buffer讀寫操作都會以limit變量的值作爲上限。 |
我們通過ByteBuffer.allocate(11)方法創建了一個11個byte的數組的緩衝區,初始狀態如上圖,position的位置爲0,capacity和limit默認都是數組長度。當我們寫入5個字節時,變化如下圖:
這時我們需要將緩衝區中的5個字節數據寫入Channel的通信信道,所以我們調用ByteBuffer.flip()方法,變化如下圖所示(position設回0,並將limit設成之前的position的值):
這裏再次解釋一下limit:
在寫模式下,Buffer的limit表示你最多能往Buffer裏寫多少數據。
當切換Buffer到讀模式時, limit表示你最多能讀到多少數據。因此,當切換Buffer到讀模式時,limit會被設置成寫模式下的position值。
clear方法
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
clear將緩衝區清空,一般是在重新寫緩衝區時調用。
flip方法
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
首先將limit設置爲當前位置,然後將position設置爲 0。如果已定義了標記。 常與compact方法一起使用。通常情況下,在準備從緩衝區中讀取數據時調用flip方法。
compact()方法將所有未讀的數據拷貝到Buffer起始處。然後將position設到最後一個未讀元素正後面。limit屬性依然像clear()方法一樣,設置成capacity。現在Buffer準備好寫數據了,但是不會覆蓋未讀的數據。
hasRemaining
public final boolean hasRemaining() {
return position < limit;
}
package com.hutonm.nio;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.RandomAccess;
public class Niotest {
@Test
public void method1(){
RandomAccessFile aFile = null;
try {
aFile = new RandomAccessFile("src/nio.text","rw");
FileChannel fileChannel = aFile.getChannel();
//create buffer with capacity of 1024 bytes
ByteBuffer buf = ByteBuffer.allocate(1024);
//read into buffer
int byteRead = fileChannel.read(buf);
// print byteRead
//System.out.println(byteRead);
while (byteRead != -1){
//make buffer read for read
buf.flip();
while (buf.hasRemaining()){
System.out.print((char)buf.get());
}
//清除已讀數據
buf.compact();
byteRead = fileChannel.read(buf);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
參考:
http://www.importnew.com/19816.html
http://ifeve.com/buffers/