Nio 緩沖類的基礎(chǔ)---Buffer的flip,rewind柏锄,clear等操作
nio的讀寫是要和Buffer的子類打交道的酿箭,關(guān)鍵的flip,rewind,mark,compact操作如下
首先來看一下Buffer里一些相關(guān)的成員變量:
private int mark = -1;
//指向下一個(gè)可讀或者可寫的數(shù)組下標(biāo)
private int position = 0;
//需要注意的是,這里的limit所指的位置其實(shí)是數(shù)組里不存在的位置趾娃,即初始化時(shí)候它是和capacity相等的缭嫡,這樣才能和上面的position的含義--指向下一個(gè)可讀或者可寫的數(shù)組下標(biāo)自洽
private int limit;
private int capacity;
//證明limit,獲取堆ByteBuffer的靜態(tài)方法抬闷,limit=capactity
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
1.flip操作
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
從源碼里可以看出妇蛀,執(zhí)行flip操作的時(shí)候,把limit置為position笤成,讀寫的position置為0,mark置為-1
為什么是這樣呢评架?因?yàn)楫?dāng)初始化Buffer的子類時(shí)候,position為0(從上面貼的那個(gè)代碼可以看出)炕泳,即指向下一個(gè)可以寫的位置纵诞,然后寫寫寫,然后這個(gè)時(shí)候我想讀了培遵,讀是怎么讀的呢浙芙,讀的指針還是用position作為標(biāo)記登刺,于是調(diào)用flip的作用就顯而易見了,把limit置為position茁裙,當(dāng)前的position置為0塘砸。
其實(shí)讀和寫最后都是調(diào)用的這個(gè)final方法去判斷是否滿足條件:
//java.nio.Buffer.nextGetIndex()
final int nextGetIndex() { // package-private
if (position >= limit)
throw new BufferUnderflowException();
return position++;
}
2.rewind操作
/**
* Rewinds this buffer. The position is set to zero and the mark is
* discarded.
*
* <p> Invoke this method before a sequence of channel-write or <i>get</i>
* operations, assuming that the limit has already been set
* appropriately. For example:
*
* <blockquote><pre>
* out.write(buf); // Write remaining data
* buf.rewind(); // Rewind buffer
* buf.get(array); // Copy data into array</pre></blockquote>
*
* @return This buffer
*/
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
rewind和flip操作基本相同,只是不把limit置為position
用法嘛晤锥,就是讀讀讀掉蔬,我讀了幾個(gè)了,但是這個(gè)時(shí)候我想重新再?gòu)念^開始讀矾瘾,用rewind就行了女轿。rewind的意思就是倒帶。壕翩。貼切
3.clear操作
顧名思義蛉迹,清除嘛
來貼代碼
//基本上就是把這幾個(gè)成員變量恢復(fù)為初始化時(shí)候的值
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
4.mark操作
//記錄下當(dāng)前的position位置,然鵝放妈,一旦調(diào)用flip或者rewind操作就失效了
public final Buffer mark() {
mark = position;
return this;
}
5.reset操作
//嗯北救,把4.里面的mark值reset給position
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
6.remaining操作
//寫入模式的情況下,就是還可以寫多少個(gè)芜抒,讀模式下就是還可以讀多少個(gè)
public final int remaining() {
return limit - position;
}
7.compact操作
compact即壓縮的意思珍策,其實(shí)compact并不是Buffer定義的方法,他是ByteBuffer的一個(gè)抽象方法
使用場(chǎng)景是當(dāng)讀取了一部分?jǐn)?shù)據(jù)的時(shí)候宅倒,并且這個(gè)時(shí)候想繼續(xù)寫數(shù)據(jù)了攘宙,這個(gè)時(shí)候就要用到compact方法了,這里抽取的是HeapByteBuffer源碼里的compact方法
public ByteBuffer compact() {
//把數(shù)組里未讀取的字節(jié)搬到字節(jié)從數(shù)組下表0開始的位置來
System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
//重新設(shè)置position拐迁,即把position指向下一個(gè)可以寫的數(shù)組下標(biāo)位置
position(remaining());
//重新設(shè)置limit蹭劈,設(shè)置為capacity()
limit(capacity());
discardMark();
return this;
}
所以Buffer類的用法:
1.申請(qǐng)到了Bufffer后,直接可以執(zhí)行寫;
2.讀操作的時(shí)候线召,flip;
3.如果想要重新讀铺韧,rewind;
4.如果讀了一部分,想要繼續(xù)寫缓淹,compact;