java.nio.ByteBuffer 以及flip,clear及rewind區別

Buffer 類java


定義了一個能夠線性存放primitive type數據的容器接口。Buffer主要包含了與類型(byte, char…)無關的功能。數組

值得注意的是Buffer及其子類都不是線程安全的。安全

每一個Buffer都有如下的屬性:函數

capacity
這個Buffer最多能放多少數據。capacity通常在buffer被建立的時候指定。
post

limit
在Buffer上進行的讀寫操做都不能越過這個下標。當寫數據到buffer中時,limit通常和capacity相等,當讀數據時,
limit表明buffer中有效數據的長度。
性能

position
讀/寫操做的當前下標。當使用buffer的相對位置進行讀/寫操做時,讀/寫會從這個下標進行,並在操做完成後,
buffer會更新下標的值。
this

mark
一個臨時存放的位置下標。調用mark()會將mark設爲當前的position的值,之後調用reset()會將position屬性設
置爲mark的值。mark的值老是小於等於position的值,若是將position的值設的比mark小,當前的mark值會被拋棄掉。
spa

這些屬性老是知足如下條件:
0 <= mark <= position <= limit <= capacity
線程

limit和position的值除了經過limit()和position()函數來設置,也能夠經過下面這些函數來改變:orm

 

Buffer clear()

public final Buffer clear() {
position = 0; //設置爲0
limit = capacity; //極限和容量相同
mark = -1; //取消標記
return this;
} 
把position設爲0,把limit設爲capacity,通常在把數據寫入Buffer前調用。

 

Buffer flip()

public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
} 
把limit設爲當前position,把position設爲0,通常在從Buffer讀出數據前調用。

 

Buffer rewind()

public final Buffer rewind() {
position = 0;
mark = -1;
return this;
} 
把position設爲0,limit不變,通常在把數據重寫入Buffer前調用。

 

Buffer對象有多是隻讀的,這時,任何對該對象的寫操做都會觸發一個ReadOnlyBufferException。
isReadOnly()方法能夠用來判斷一個Buffer是否只讀

舉例補充(摘自百度知道):

ByteBuffer 的filp函數, 將緩衝區的終止位置limit設置爲當前位置, 緩衝區的遊標position(當前位置)重設爲0.
好比 咱們有初始化一個ByteBuffer 後有
ByteBuffer buffer = ByteBuffer.allocate(1024);
這是 終止位置limit在1024, 而起始位置position在 0
若是咱們添加一個數據,
buffer.putint(90);
這會使起始位置 position 移到4, 也就是說postion始終都在第一個可寫字節的位置上. limit 則不會發生改變
而若是這時,咱們調用
buffer.flip();
position轉到0, limit轉到 4 也就是原來的position 所在位置
這裏的flip, 從另一個角度上來講, 是在讀數據時,操做的
然而, 若是我此時在寫
buffer.putInt(90);
就會將原來的覆蓋掉
若是咱們在寫, 這時就不行了, 就會重現問題了. 由於咱們的limit是4, 咱們寫入數據不能超過這個limit,(固然還有capacity)
因此在寫的時候,最好先清空buffer.clear();
若是真的不想清空, 也能夠調用
buffer.limit(newlimit);
設置一個較大的limit, 再寫入
固然不能超過capacity, 能夠等於 capacity


 

ByteBuffer 類

在Buffer的子類中,ByteBuffer是一個地位較爲特殊的類,由於在java.io.channels中定義的各類channel的IO
操做基本上都是圍繞ByteBuffer展開的。

ByteBuffer定義了4個static方法來作建立工做:

ByteBuffer allocate(int capacity) //建立一個指定capacity的ByteBuffer。
ByteBuffer allocateDirect(int capacity) //建立一個direct的ByteBuffer,這樣的ByteBuffer在參與IO操做時性能會更好
ByteBuffer wrap(byte [] array)
ByteBuffer wrap(byte [] array, int offset, int length) //把一個byte數組或byte數組的一部分包裝成ByteBuffer。

ByteBuffer定義了一系列get和put操做來從中讀寫byte數據,以下面幾個:
byte get()
ByteBuffer get(byte [] dst)
byte get(int index)
ByteBuffer put(byte b)
ByteBuffer put(byte [] src)
ByteBuffer put(int index, byte b) 
這些操做可分爲絕對定位和相對定爲兩種,相對定位的讀寫操做依靠position來定位Buffer中的位置,並在操
做完成後會更新position的值。在其它類型的buffer中,也定義了相同的函數來讀寫數據,惟一不一樣的就是一
些參數和返回值的類型。

除了讀寫byte類型數據的函數,ByteBuffer的一個特別之處是它還定義了讀寫其它primitive數據的方法,如:

int getInt() //從ByteBuffer中讀出一個int值。
ByteBuffer putInt(int value)
 // 寫入一個int值到ByteBuffer中。

讀寫其它類型的數據牽涉到字節序問題,ByteBuffer會按其字節序(大字節序或小字節序)寫入或讀出一個其它
類型的數據(int,long…)。字節序能夠用order方法來取得和設置:
ByteOrder order() //返回ByteBuffer的字節序。
ByteBuffer order(ByteOrder bo) //
 設置ByteBuffer的字節序。

ByteBuffer另外一個特別的地方是能夠在它的基礎上獲得其它類型的buffer。如:
CharBuffer asCharBuffer()
爲當前的ByteBuffer建立一個CharBuffer的視圖。在該視圖buffer中的讀寫操做會按照ByteBuffer的字節
序做用到ByteBuffer中的數據上。

用這類方法建立出來的buffer會從ByteBuffer的position位置開始到limit位置結束,能夠看做是這段數據的視圖。視圖buffer的readOnly屬性和direct屬性與ByteBuffer的一致,並且也只有經過這種方法,纔可以獲得其餘數據類型的direct buffer。

相關文章
相關標籤/搜索