NIO:關於ByteBuffer的幾個關鍵屬性

byteBuffer幾個方法含義:  java

  •       capacity:緩衝區的容量;
  •   limit:緩衝區還有多少數據可以取出或者緩衝區還有多少容量用於存放數據;
  •   position:至關於一個遊標(cursor),記錄咱們從哪裏開始寫數據,從哪裏開始讀數據。

三者關係:函數

  • capacity表明了Buffer的容量是不變的;
  • limit與position的差老是表示Buffer總能夠讀的數據,或者Buffer中能夠寫數據的容量。
  • position老是小於等於limit,limit老是小於等於capacity。

ByteBuffer主要標誌位說明

標誌位 初始值 說明
mark -1 標記位
position 0 當前位置
limit 指定的緩衝區容量 已寫入有效數據容量
capacity 指定的緩衝區容量 緩衝區容量

 

ByteBuffer的初始化

ByteBuffer提供兩種不一樣的構造函數,其本質主要是構建的ByteBuffer類型不一樣,其中一種構造函數參照源代碼:性能

//第一種,分配的是DirectByteBuffer
  public static ByteBuffer allocateDirect(int capacity) {
        return new DirectByteBuffer(capacity);
  }
  //第二種,分配的是HeapByteBuffer
  public static ByteBuffer allocate(int capacity) {
        if (capacity < 0)
            throw new IllegalArgumentException();
        return new HeapByteBuffer(capacity, capacity);
  }

詳細兩種不一樣類型的Buffer這裏不展開討論,可是大多數狀況下,若是對性能沒有太大要求的話,通常默認使用HeapByteBuffer。當咱們執行初始化操做後: ByteBuffer.allocate(緩衝區大小);this

其中初始化的值,分別爲position=0,limit和capacity等於咱們指定的緩衝區大小,mark默認爲-1。網上有一些教程的圖示默認顯示了mark爲起始點,實際上是一種低級錯誤,讓別人誤覺得mark就等於起始位置。spa

Put操做

顧名思義,put操做就是就是將數據放入緩衝區中,每一次put操做,都會position加上put進去的數據長度.position每加一,表明緩衝區內增長了一個字節的數據,具體put的操做原理以下: code

若是送入的數據大小大於緩衝區剩餘容量,則會拋出異常:java.nio.BufferOverflowException,雖然可能有實際部分數據被寫入緩衝區,可是flip以後,limit位置仍是最後一次正確寫入緩衝區的位置。教程

Flip操做

Flip,回針(請聯想老式打字機),是讓limit指向當前position的位置,position指向起始位置,此時position=0,進行這一部操做以後,就能夠肯定了當前緩衝區的有效數據。而且爲數據讀取作準備。ip

Get操做

Get操做,就是按照position當前位置,取出緩衝區的數據,每一次取操做以後,position都會get出的數據長度。一樣,position每加一,表明從緩衝區內讀取到了一個字節的數據,不過數據並不會被刪除,只是單純的讀取操做。若是,get以後,position值大於limit值,則拋出異常:java.nio.BufferUnderflowExceptionci

Mark操做和Reset操做

mark,就是標記當前的位置,一旦後續進行reset操做以後,能夠快速地定位到mark的位置。在某一些應用場合中,配合reset,這是一個很是方便的操做函數。get

一旦進行過mark操做以後,後續讀取操做中,若是再執行reset操做,就能夠快速定位到標記位上:

 

Clear操做

Clear操做很簡單,就是全部標誌位都會被恢復成默認值,包括mark值,可是記住,不是數據,寫入緩衝區的數據仍然保留,若是這時候執行get操做,仍然能夠將數據獲取出來。直觀的話,能夠直接看源代碼:

public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

Slice操做

slice方法的做用,就是作數據分割,將當前的position到limit之間的數據分割出來,返回一個新的ByteBuffer,同時,mark標記重置爲-1。不過這裏注意,分割出來的數據的容量恰好就是數據長度,而不是被分割以前的長度。

快速清除已讀取的數據

有時候,咱們只是想要去掉前面一部分,而保留後面一部分數據,同時保持緩衝區的大小不變呢,這裏提供一種思路,以下:

public void clearPrePositionData(ByteBuffer byteBuffer) {
        ByteBuffer buffer2 = byteBuffer.slice();
        byteBuffer.clear();
        if (buffer2.capacity() > 0) {

            byteBuffer.put(buffer2);
        } else {
            byteBuffer.mark();
            byteBuffer.reset();
        }
        byteBuffer.flip();
    }
相關文章
相關標籤/搜索