Java Nio 的Buffer
在數據傳輸的時候,我們會用到緩衝區。Java NIO中的Buffer用於和NIO通道進行交互。如你所知,數據是從通道讀入緩衝區,從緩衝區寫入到通道中的。緩衝區本質上是一塊可以寫入數據,然後可以從中讀取數據的內存。這塊內存被包裝成NIO Buffer對象,並提供了一組方法,用來方便的訪問該塊內存。Java的NIO 爲我們提供了原生的八種緩衝區實現,對應着Java 的七種基本類型和MappedByteBuffer。
Java NIO 有以下Buffer類型
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
Java中的這些Buffer已經足夠我們使用,但是這些確實基本的操作,在複雜的應用的時候就需要我們自己去封裝。由此我們可以知道netty爲什麼對java 的nio進行封裝了。
- 原生的Buffer,在創建緩存區的時候分指定分配的空間。一旦創建,就不能動態的擴展。
- 原生的Buffer中只有一個位置標記位,我們能修改通過操作這個標記爲來實現訪問和存取容易出錯。
- Buffer簡單功能的函數,需要我們自己實現複雜函數。
操作位置的函數
對緩衝區的讀寫操作首先要知道緩衝區的下限、上限和當前位置。下面這些變量的值對Buffer類中的某些操作有着至關重要的作用:
- limit:所有對Buffer讀寫操作都會以limit變量的值作爲上限。
- position:代表對緩衝區進行讀寫時,當前遊標的位置。
- capacity:代表緩衝區的最大容量(一般新建一個緩衝區的時候,limit的值和capacity的值默認是相等的)。
clear方法將緩衝區清空,一般是在重新寫緩衝區時調用。
public final Buffer clear() {
position = 0; //重置當前讀寫位置
limit = capacity;
mark = -1; //取消標記
return this;
}
反轉緩衝區。首先將限制設置爲當前位置,然後將位置設置爲 0。通常情況下,在準備從緩衝區中讀取數據時調用flip方法。
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
使緩衝區爲重新讀取已包含的數據做好準備:它使限制保持不變,將位置設置爲 0。
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
以上三種方法均使用final修飾,java.nio.Buffer的所有子類均使用同一種flip、clear和rewind機制。
這三個方法在源碼上就對緩衝區的數據不進行任何修改。
一旦讀完了所有的數據,就需要清空緩衝區,讓它可以再次被寫入。有兩種方式能清空緩衝區:調用clear()或compact()方法。clear()方法會清空整個緩衝區。compact()方法只會清除已經讀過的數據。任何未讀的數據都被移到緩衝區的起始處,新寫入的數據將放到緩衝區未讀數據的後面。
其他函數
Buffer的分配
每一個Buffer類都有一個allocate方法。
ByteBuffer buf = ByteBuffer.allocate(48);
向Buffer中寫數據
寫數據到Buffer有兩種方式:
- 從Channel寫到Buffer。
int bytesRead = inChannel.read(buf); //read into buffer.
- 通過Buffer的put()方法寫到Buffer裏。
buf.put(127);
- 從Channel寫到Buffer。
從Buffer中讀取數據
從Buffer中讀取數據有兩種方式:
- 從Buffer讀取數據到Channel。
int bytesWritten = inChannel.write(buf);
- 使用get()方法從Buffer中讀取數據。
byte aByte = buf.get();
- 從Buffer讀取數據到Channel。
mark()與reset()方法
通過調用Buffer.mark()方法,可以標記Buffer中的一個特定position。之後可以通過調用Buffer.reset()方法恢復到這個position。
equals()與compareTo()方法
可以使用equals()和compareTo()方法比較兩個Buffer。
equals()
當滿足下列條件時,表示兩個Buffer相等:
- 有相同的類型(byte、char、int等)。
- Buffer中剩餘的byte、char等的個數相等。
- Buffer中所有剩餘的byte、char等都相同。
如你所見,equals只是比較Buffer的一部分,不是每一個在它裏面的元素都比較。實際上,它只比較Buffer中的剩餘元素。
compareTo()方法
compareTo()方法比較兩個Buffer的剩餘元素(byte、char等), 如果滿足下列條件,則認爲一個Buffer“小於”另一個Buffer:
- 第一個不相等的元素小於另一個Buffer中對應的元素 。
- 所有元素都相等,但第一個Buffer比另一個先耗盡(第一個Buffer的元素個數比另一個少)。
應用舉例
public static void main(String[] args) throws IOException {
RandomAccessFile aFile = new RandomAccessFile("input/input.txt", "rw");
FileChannel inChannel = aFile.getChannel();
//create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
System.out.print((char) buf.get()); // read 1 byte at a time
}
System.out.println("bytesRead = " + bytesRead);
buf.clear();//make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();
}
參考資料:
網上資料
備註:
轉載請註明出處:http://blog.csdn.net/wsyw126/article/details/75208264
作者:WSYW126