NIO介紹
Java NIO(New IO)是從Java 1.4版本開(kāi)始引入的一個(gè)新的IO API,可以替代標(biāo)準(zhǔn)的Java IO API。
- Channels and Buffers(通道和緩沖區(qū)):標(biāo)準(zhǔn)的IO基于字節(jié)流和字符流進(jìn)行操作的,而NIO是基于通道(Channel)和緩沖區(qū)(Buffer)進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。
本文主要介紹ByteBuffer的常用方法
- Buffer 以下實(shí)現(xiàn)
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
一、首先介紹三個(gè)參數(shù)

image.png
- capacity
- position
- limit
String text = "123456789";
ByteBuffer byteBuffer = ByteBuffer.allocate(15);
byteBuffer.put(text.getBytes());//將text復(fù)制到緩沖區(qū)
//TODO 開(kāi)始都去緩沖區(qū),如果不進(jìn)行flip,那么預(yù)測(cè),byteBuffer lim=15,pos=9,cap=15
System.out.println(byteBuffer);//java.nio.HeapByteBuffer[pos=9 lim=15 cap=15]
//雖然pos等于9但是因?yàn)樗饕菑?開(kāi)始的,那么在預(yù)測(cè)pos 8為止等于上面text的9
System.out.println("預(yù)測(cè)pos 8為止等于:" + (char) byteBuffer.get(8));//預(yù)測(cè)成功:預(yù)測(cè)pos 8為止等于:9
FIXME 由此解釋:position limit capacity
- position在未寫入數(shù)據(jù)時(shí)候?yàn)?,當(dāng)寫入數(shù)據(jù),就變?yōu)閷懭霐?shù)據(jù)長(zhǎng)度的下一個(gè)可寫的位置
text最后一個(gè)數(shù)的索引位置是8,所以在byteBuffer中position下一個(gè)可以寫的位置就是9,而8位置,就對(duì)應(yīng)了text中最后一個(gè)數(shù)9
- capacity等于緩沖區(qū)的長(zhǎng)度
- limit可以理解為寫入數(shù)據(jù)的長(zhǎng)度,當(dāng)初始化沒(méi)有數(shù)據(jù)時(shí)候,就等于capacity的長(zhǎng)度。而當(dāng)寫入數(shù)據(jù)時(shí)候就變成了數(shù)據(jù)的長(zhǎng)度
當(dāng)讀到這里,就可以對(duì)預(yù)測(cè)的明白了。
二、開(kāi)始新的高級(jí)學(xué)習(xí),讀寫操作
- flip(); 這個(gè)方法用于重置pos位置當(dāng)寫的時(shí)候位置為可寫的位置,但是讀的時(shí)候如果不重置,讀取的就是沒(méi)有數(shù)據(jù)的位置.用于讀寫轉(zhuǎn)換
String text = "123456789";
ByteBuffer byteBuffer = ByteBuffer.allocate(15);
byteBuffer.put(text.getBytes());//將text復(fù)制到緩沖區(qū)
//開(kāi)始讀取
//我們要從0開(kāi)始讀,到lim位置,而這個(gè)方法就是把pos=0,lim=數(shù)據(jù)長(zhǎng)度
byteBuffer.flip();//預(yù)測(cè):pos=0,lim=9,cap=15
System.out.println(byteBuffer);//java.nio.HeapByteBuffer[pos=0 lim=9 cap=15]
for (int i = 0; i < byteBuffer.limit(); i++) {
System.out.print((char) byteBuffer.get(i));//123456789
}
假設(shè)不進(jìn)行flip就會(huì)讀空數(shù)據(jù),那么由于我們轉(zhuǎn)為char 所以出來(lái)就是亂碼123456789[][][]
- clear();這個(gè)方法會(huì)把pos=0 lim=15 cap=15,等于把byteBuffer對(duì)象重置了
byteBuffer.clear();
System.out.println(byteBuffer);
- rewind();這個(gè)方法會(huì)重置pos=0 其他維持原樣 為讀取有效數(shù)據(jù)
- get();獲得最后limit位置數(shù)據(jù)
- get(int index);獲取制定位置數(shù)據(jù)
- get(byte arr);復(fù)制有效數(shù)據(jù)到arr數(shù)組
- put(byte arr);把a(bǔ)rr數(shù)據(jù)寫入到緩沖區(qū)
- put(int index,byte arr);把a(bǔ)rr寫入到指定位置
三、 標(biāo)記方法,具有回滾功能,這兩個(gè)方法不解釋,只演示
- mark();
- reset();
byteBuffer.put(text.getBytes());//因?yàn)樯厦嬉呀?jīng)清理了,所以在此將text復(fù)制到緩沖區(qū)
for (int i = 0; i < 8; i++) {
if (i == 1) {
byteBuffer.mark();//標(biāo)記1位置開(kāi)始寫新數(shù)據(jù)
byteBuffer.put(1, ((byte) '4'));//此時(shí)預(yù)測(cè)數(shù)據(jù)為:143456789
}
}
// byteBuffer.reset();//回到標(biāo)記位置
byteBuffer.flip();
for (int i = 0; i < byteBuffer.limit(); i++) {
System.out.print((char) byteBuffer.get(i));//143456789 ,預(yù)測(cè)成功
}
四、復(fù)制緩沖區(qū)
byteBuffer.clear();
byteBuffer.put(text.getBytes());//將text復(fù)制到緩沖區(qū)
ByteBuffer byteBuffer1 = byteBuffer.duplicate();
System.out.println(byteBuffer); //[pos=9 lim=15 cap=15]
System.out.println(byteBuffer1); //[pos=9 lim=15 cap=15]
//但是當(dāng)修改一個(gè)地方,另一個(gè)緩沖區(qū)也會(huì)變化 ,這個(gè)變化是內(nèi)容變化,但是pos lim cap不改變
//開(kāi)始試驗(yàn),將1的插入新數(shù)據(jù)
byteBuffer1.flip(); //重置寫
byteBuffer1.put((byte) 'A');
System.out.println(byteBuffer); //[pos=9 lim=15 cap=15]
System.out.println(byteBuffer1); //[pos=10 lim=15 cap=15] 因?yàn)樘砑恿?,所以pos位置變了
//開(kāi)始獲取,這個(gè)兩個(gè)最后一個(gè)數(shù)據(jù),預(yù)測(cè),都是A。
System.out.println((char) byteBuffer.get(0)); //A
System.out.println((char) byteBuffer1.get(0)); //A
此方法有個(gè)特殊的地方就是:當(dāng)修改一個(gè)地方,另一個(gè)緩沖區(qū)也會(huì)變化 ,這個(gè)變化是內(nèi)容變化,但是pos lim cap不改變
附錄
- NIO是高效的IO處理方式,如果感興趣的筆者推薦可以和筆者一起深入學(xué)習(xí)Netty框架,快速開(kāi)發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序
- 其次Buffer的使用方法遠(yuǎn)不止如此,筆者這里只使用常用方法