Buffer是緩存逊彭,Buffer的作用是和NIO通道(Channel)進(jìn)行交互。
查閱資料知道:
緩沖區(qū)本質(zhì)上是一塊可以寫入數(shù)據(jù)构订,然后可以從中讀取數(shù)據(jù)的內(nèi)存侮叮。這塊內(nèi)存被包裝成NIO Buffer對(duì)象,并提供了一組方法悼瘾,用來方便的訪問該塊內(nèi)存囊榜。
Buffer的使用
總共分為四步:
1.寫數(shù)據(jù)到Buffer
2.調(diào)用flip()方法
3.從Buffer中讀取數(shù)據(jù)
4.調(diào)用clear()方法或者compact()方法
上一篇文章寫Channel測試的時(shí)候也簡單使用了Buffer。這里說一下clear()和compact()方法亥宿。他們都可以在讀取完畢之后清空緩存區(qū)卸勺,為以后的數(shù)據(jù)寫入做準(zhǔn)備,他們的區(qū)別在于:clear()方法會(huì)清空整個(gè)緩沖區(qū)烫扼。compact()方法只會(huì)清除已經(jīng)讀過的數(shù)據(jù)曙求。未讀過的數(shù)據(jù)會(huì)留在緩存區(qū)中,隨著后面讀入的數(shù)據(jù)一起等下一次的filp()材蛛。
這里用代碼簡單的使用一下:
public class TestBuffer {
public static void main(String[] args) throws IOException {
Charset charset = Charset.forName("utf-8");
CharsetDecoder decoder = charset.newDecoder();
RandomAccessFile file = new RandomAccessFile("nio-data.txt","rw");
FileChannel channel = file.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
CharBuffer cb = CharBuffer.allocate(48);
int count = channel.read(buf);
while (count!=-1){
buf.flip();
decoder.decode(buf,cb,false);
cb.flip();
while (cb.hasRemaining()){
System.out.print(cb.get());
}
buf.compact();
cb.compact();
count = channel.read(buf);
}
file.close();
}
}
這里我開始使用compact()而不是clear()了圆到。
接下來學(xué)習(xí)一下Buffer的原理
它有三個(gè)重要的屬性:
- capacity(容量)
- position(位置)
- limit(界限)
position和limit的含義取決于Buffer處在讀模式還是寫模式怎抛。
capacity不然卑吭。
capacity(容量)
翻譯來是容量,很好理解马绝,既然是容量就又固定的大小豆赏,一旦Buffer滿了,我們就需要對(duì)其清空,然后才能繼續(xù)使用它掷邦。
position(位置)
寫模式:position表示數(shù)據(jù)當(dāng)前的位置白胀,會(huì)隨著數(shù)據(jù)的寫入不斷的移動(dòng),直到達(dá)到容量抚岗,position最大為capacity-1或杠。
讀模式:當(dāng)我們讀取數(shù)據(jù)時(shí),Buffer會(huì)從寫模式切換到讀模式宣蔚,然后position會(huì)清0向抢,position會(huì)移動(dòng)到可讀的位置。
limit(界限)
寫模式:limit表示我們還能向Buffer中寫多少數(shù)據(jù)胚委,此模式下limit等于capacity挟鸠。
讀模式:此模式下,limit表示我們可以從Buffer度多少數(shù)據(jù)亩冬,此時(shí)limit會(huì)設(shè)置為寫模式下的position值艘希。
其實(shí)有數(shù)據(jù)結(jié)構(gòu)的線性結(jié)構(gòu)的思想,理解起來就會(huì)很簡單硅急,可以通過復(fù)習(xí)數(shù)組覆享、鏈表、隊(duì)列和棧來回憶~
Buffer使用(細(xì)化)
為Buffer分配空間
前面練習(xí)有對(duì)Buffer分配空間的代碼营袜,這里提取出來單獨(dú)記:
ByteBuffer buf = ByteBuffer.allocate(48);
這就分配好了淹真,這里只是Byte類型,我們還可以使用很多基本類型的buffer连茧,就是可以通過char核蘸,short,int啸驯,long客扎,float 或 double類型來操作緩沖區(qū)中的字節(jié)。
向Buffer寫數(shù)據(jù)
我們可以選擇兩種方式去寫數(shù)據(jù):
1.用Channel向Buffer寫
int bytesRead = inChannel.read(buf); //read into buffer.
2.用Buffer自帶的put()方法
buf.put(127);
從Buffer讀數(shù)據(jù)
這之前先說個(gè)filp()方法罚斗,filp()這個(gè)辦法徙鱼,會(huì)將Buffer從寫模式切換成讀模式,將position設(shè)置為0针姿,并將limit設(shè)置成之前position的值袱吆,也就是說:position現(xiàn)在用于標(biāo)記讀的位置,limit表示之前寫進(jìn)了多少個(gè)byte距淫、char等 —— 現(xiàn)在能讀取多少個(gè)byte绞绒、char等。
讀數(shù)據(jù)也有兩種方式:
1.從Channel里讀
int bytesWritten = inChannel.write(buf);
2.用Buffer的get()方法
byte aByte = buf.get();
記一下rewind()方法
Buffer.rewind()會(huì)將position設(shè)回0榕暇,所以使用后蓬衡,我們可以重讀Buffer中的所有數(shù)據(jù)喻杈。
記一下clear()與compact()方法
前面有簡單的記過,這里具體說一說狰晚,當(dāng)我們讀完buffer中的數(shù)據(jù)之后筒饰,要將緩存清空,這時(shí)候就需要使用到這倆方法壁晒,可以根據(jù)實(shí)際情況任選其一~
clear()是清除所有的緩存瓷们。
compact()是清除已經(jīng)讀過的緩存。
clear()會(huì)把position設(shè)回0秒咐,limit被設(shè)置成 capacity的值换棚。
compact()將position設(shè)到最后一個(gè)未讀元素正后面。limit屬性依然像clear()方法一樣反镇,設(shè)置成capacity固蚤。
記一下mark()與reset()方法
buffer.mark();
buffer.reset();
通過調(diào)用Buffer.mark()方法,可以標(biāo)記Buffer中的一個(gè)特定position歹茶。之后可以通過調(diào)用Buffer.reset()方法恢復(fù)到這個(gè)position夕玩。
equals()與compareTo()方法
先說equals()
Q:什么情況下equals()返回true呢?
A:需要滿足以下情況:
1.類型相同
2.Buffer中剩余的byte惊豺、char等的個(gè)數(shù)相同
3.Buffer中所有剩余的byte燎孟、char等都相同。
所以Buffer中尸昧,equals()揩页,比較的是Buffer的剩余部分
Q:compareTo()方法是啥?
A:compareTo是比較兩個(gè)Buffer的剩余元素的(byte烹俗、char等)
什么情況下一個(gè)Buffer小于另一個(gè)Buffer呢爆侣?
1.第一個(gè)不相等的元素小于另一個(gè)Buffer中對(duì)應(yīng)的元素 。
2.所有元素都相等幢妄,但第一個(gè)Buffer比另一個(gè)先耗盡(第一個(gè)Buffer的元素個(gè)數(shù)比另一個(gè)少)兔仰。
Scatter和Gather
這里yi