Buffer的基本的原理
在談到緩沖區(qū)時,我們說緩沖區(qū)對象本質(zhì)上是一個數(shù)組,但它其實是一個特殊的數(shù)組,緩沖區(qū)對象內(nèi)置了一些機(jī)制,能夠跟蹤和記錄緩沖區(qū)的狀態(tài)變化情況,如果我們使用get()方法從緩沖區(qū)獲取數(shù)據(jù)或者使用put()方法把數(shù)據(jù)寫入緩沖區(qū),都會引起緩沖區(qū)狀態(tài)的變化。
在緩沖區(qū)中,最重要的屬性有下面三個,它們一起合作完成對緩沖區(qū)內(nèi)部狀態(tài)的變化跟蹤:
position:指定下一個將要被寫入或者讀取的元素索引,它的值由get()/put()方法自動更新,在新創(chuàng)建一個Buffer 對象時,position 被初始化為0。
limit:指定還有多少數(shù)據(jù)需要取出(在從緩沖區(qū)寫入通道時),或者還有多少空間可以放入數(shù)據(jù)(在從通道讀入緩沖區(qū)時)。
capacity:指定了可以存儲在緩沖區(qū)中的最大數(shù)據(jù)容量,實際上,它指定了底層數(shù)組的大小,或者至少是指定了準(zhǔn)許我們使用的底層數(shù)組的容量。
以上三個屬性值之間有一些相對大小的關(guān)系:0 <= position <= limit <= capacity。如果我們創(chuàng)建一個新的容量大小為10 的ByteBuffer 對象,在初始化的時候,position 設(shè)置為0,limit 和capacity 被設(shè)置為10,在以后使用ByteBuffer對象過程中,capacity 的值不會再發(fā)生變化,而其它兩個個將會隨著使用而變化。
下面我們用代碼來演示一遍,準(zhǔn)備一個txt 文檔,存放的E 盤,輸入以下內(nèi)容:
Tom.下面我們用一段代碼來驗證position、limit 和capacity 這幾個值的變化過程,代碼如下:
import java.io.FileInputStream; import java.nio.*; import java.nio.channels.*; public class BufferDemo {public static void main(String args[]) throws Exception {//這用用的是文件IO 處理FileInputStream fin = new FileInputStream("E://test.txt");//創(chuàng)建文件的操作管道FileChannel fc = fin.getChannel();//分配一個10 個大小緩沖區(qū),說白了就是分配一個10 個大小的byte 數(shù)組ByteBuffer buffer = ByteBuffer.allocate(10);output("初始化", buffer);//先讀一下fc.read(buffer);output("調(diào)用read()", buffer);//準(zhǔn)備操作之前,先鎖定操作范圍buffer.flip();output("調(diào)用flip()", buffer);//判斷有沒有可讀數(shù)據(jù)while (buffer.remaining() > 0) {byte b = buffer.get();// System.out.print(((char)b));}output("調(diào)用get()", buffer);//可以理解為解鎖buffer.clear();output("調(diào)用clear()", buffer);//最后把管道關(guān)閉fin.close();}//把這個緩沖里面實時狀態(tài)給答應(yīng)出來public static void output(String step, Buffer buffer) {System.out.println(step + " : ");//容量,數(shù)組大小System.out.print("capacity: " + buffer.capacity() + ", ");//當(dāng)前操作數(shù)據(jù)所在的位置,也可以叫做游標(biāo)System.out.print("position: " + buffer.position() + ", ");//鎖定值,flip,數(shù)據(jù)操作范圍索引只能在position - limit 之間System.out.println("limit: " + buffer.limit());System.out.println();} }完成的輸出結(jié)果為:
運(yùn)行結(jié)果我們已經(jīng)看到,下面呢對以上結(jié)果進(jìn)行圖解,四個屬性值分別如圖所示:
我們可以從通道中讀取一些數(shù)據(jù)到緩沖區(qū)中,注意從通道讀取數(shù)據(jù),相當(dāng)于往緩沖區(qū)中寫入數(shù)據(jù)。如果讀取4 個自己的數(shù)據(jù),則此時position 的值為4,即下一個將要被寫入的字節(jié)索引為4,而limit 仍然是10,如下圖所示:
下一步把讀取的數(shù)據(jù)寫入到輸出通道中,相當(dāng)于從緩沖區(qū)中讀取數(shù)據(jù),在此之前,必須調(diào)用flip()方法,該方法將會完成兩件事情:
1. 把limit 設(shè)置為當(dāng)前的position 值
2. 把position 設(shè)置為0
由于position 被設(shè)置為0,所以可以保證在下一步輸出時讀取到的是緩沖區(qū)中的第一個字節(jié),而limit 被設(shè)置為當(dāng)前的position,可以保證讀取的數(shù)據(jù)正好是之前寫入到緩沖區(qū)中的數(shù)據(jù),如下圖所示:
現(xiàn)在調(diào)用get()方法從緩沖區(qū)中讀取數(shù)據(jù)寫入到輸出通道,這會導(dǎo)致position 的增加而limit 保持不變,但position 不會超過limit 的值,所以在讀取我們之前寫入到緩沖區(qū)中的4 個自己之后,position 和limit 的值都為4,如下圖所示:
在從緩沖區(qū)中讀取數(shù)據(jù)完畢后,limit 的值仍然保持在我們調(diào)用flip()方法時的值,調(diào)用clear()方法能夠把所有的狀態(tài)變化設(shè)置為初始化時的值,如下圖所示:
?
總結(jié)
以上是生活随笔為你收集整理的Buffer的基本的原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。