JAVA NIO 翻譯系列(三、Buffer)

Buffer的基本使用

利用buffer讀寫數(shù)據(jù)主要走下面4小步驟

1)數(shù)據(jù)寫入到buffer中

2)調(diào)用buffer.flip()

3)從buffer中讀取數(shù)據(jù)

4)調(diào)用buffer.clear()或者buffer.compact()

當(dāng)你寫數(shù)據(jù)到buffer中時(shí),buffer會記住你已經(jīng)寫入到多少數(shù)據(jù)了。一旦你需要從buffer中讀取數(shù)據(jù)了,你需要調(diào)用它的flip()方法,將寫模式切換成讀模式,在讀模式下,buffer允許你讀取所有寫在它里面的數(shù)據(jù)。

注意:讀原文的時(shí)候,讀寫感覺到有點(diǎn)繞,特別是channel.read(buffer), 雖然是個(gè)read方法,但是此時(shí)buffer是出于寫模式下的,因?yàn)镃hannel將數(shù)據(jù)寫入到buffer中,所以讀寫模式是對于buffer來說的。數(shù)據(jù)放入buffer中就是寫,數(shù)據(jù)從buffer中出去就是讀。

一旦你從buffer中讀完數(shù)據(jù)了,你需要清空buffer,準(zhǔn)備好下次寫數(shù)據(jù)進(jìn)去。清空可以通過clear方法或者compact方法來實(shí)現(xiàn)。clear方法可以清空整個(gè)buffer。compact方法會清空你已經(jīng)讀取過的數(shù)據(jù),任何未讀的數(shù)據(jù)會被移動到buffer的開頭處,后面再像buffer寫數(shù)據(jù)的時(shí)候,數(shù)據(jù)會繼續(xù)追加在前面的數(shù)據(jù)后面。(恩,有點(diǎn)像拿吸管喝一杯可樂,管子插到杯子底部,你吸了一部分可樂,剩下的可樂會自動向下移動到某個(gè)位置,當(dāng)你添加可樂的時(shí)候,所加的可樂也是在剩下的可樂的移動后的位置上追加的,不是太恰當(dāng),是這么個(gè)意思==?。?/p>

下面是一個(gè)小例子,幾個(gè)操作都在里面


Buffer 中的Capacity, Position and Limit

一個(gè)buffer本質(zhì)上就是一塊內(nèi)存,你可以往這這個(gè)內(nèi)存寫數(shù)據(jù),再讀取。JAVA NIO BUFFER對象將這塊內(nèi)存封裝起來,對外暴露一些api接口,方便使用者操作這塊內(nèi)存。

為了理解buffer,你得熟悉三個(gè)概念Capacity, Position and Limit。其中Position和Limit的具體含義取決于buffer是處在讀還是寫模式下,Capacity則不管是讀還是寫,總是表示buffer的容量。

下面是一個(gè)圖解:


Buffer capacity, position and limit in write and read mode.

Capacity

在內(nèi)存塊中,一個(gè)buffer有一個(gè)確定的大小,成為capacity。你總共只能寫capacity個(gè)bytes,longs,chars等到buffer中,多一個(gè)也寫不進(jìn)去。一旦buffer滿了,一旦buffer滿了,在你下次寫數(shù)據(jù)之前,你需要清空它(從buffer中讀或者clear)。

Position

寫模式下,是從buffer中某一個(gè)確定的position開始寫的。position初始化為0。當(dāng)一個(gè)byte或者long型的數(shù)據(jù)寫入到buffer中的時(shí)候,postion的位置就遞增一個(gè),你可以理解為指針,指向下一個(gè)位置。因?yàn)閎uffer最大容量為capacity,0代表第一個(gè)位置,所以position的最大值必然為capacity-1.

讀模式下,也是從某一個(gè)確定的position開始的,當(dāng)你調(diào)用buffer.flip()方法的時(shí)候,會從寫模式切換到讀模式,position會被設(shè)置為0。當(dāng)你從buffer的position位置開始讀的時(shí)候,每讀取一個(gè),position的位置就會加1.

Limit

在寫模式下,buffer的limit就是指你可以寫limit個(gè)數(shù)據(jù)到buffer中。在寫模式下,limit就等于capacity。

當(dāng)你調(diào)用flip方法切換到讀模式下,limit就意味著你可以讀取多少個(gè)數(shù)據(jù)。當(dāng)調(diào)用flip方法的時(shí)候,limit會被設(shè)置為寫模式下的position。換句話說,你前面的寫模式下寫了多少個(gè)數(shù)據(jù),后面才能讀取多少個(gè)。

Buffer 的實(shí)現(xiàn)類型

主要有以下幾種:

ByteBuffer、MappedByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer

構(gòu)造 buffer

通過調(diào)用allocate方法來構(gòu)造一個(gè)buffer對象,下面的這個(gè)方法就是構(gòu)造了一個(gè)capacity等于48的大小的bytes。

? ? ? ? ByteBuffer buf = ByteBuffer.allocate(48);

寫數(shù)據(jù)到buffer中

1)通過channel的read方式

int bytesRead = inChannel.read(buffer); //read into buffer.

2)通過buffer自身的put方式

buffer.put(127);

還有其他的put方法,本質(zhì)都一樣

從buffer中讀數(shù)據(jù)

也有兩種方式:

1)從buffer中讀取數(shù)據(jù)到channel中

int bytesWritten = inChannel.write(buf);

2)buffer自身的get方式

byte aByte = buf.get();

rewind()

rewind是倒回的意思,當(dāng)你讀了一部分?jǐn)?shù)據(jù)之后,調(diào)用此方法之后,postion會變?yōu)?,也就是說又從頭開始讀。

clear() and compact()

一旦你從buffer讀完數(shù)據(jù)之后,為了下次能繼續(xù)往里面寫數(shù)據(jù),你必須調(diào)用clear方法或者compact方法。

如果你調(diào)用clear方法,position會被設(shè)置為0,limit會被設(shè)置為capacity。也即是說切換到寫模式了。

當(dāng)你還未讀完buffer中的數(shù)據(jù)的時(shí)候,你調(diào)用clear方法的話,那些未讀的數(shù)據(jù)也會被“遺忘”掉。如果說還有未讀完的數(shù)據(jù),這個(gè)時(shí)候你想開始寫操作,然后在讀取數(shù)據(jù)的時(shí)候回,那些之前未讀的數(shù)據(jù)你還想繼續(xù)讀取,請調(diào)用compact方法。

mark() and reset()

ou can mark a given position in aBufferby calling theBuffer.mark()method. You can then later reset the position back to the marked position by calling theBuffer.reset()method. Here is an example:

mark方法就是標(biāo)記buffer當(dāng)前的position,然后你繼續(xù)讀取buff,position位置會發(fā)生變化,此時(shí)當(dāng)你調(diào)用reset方法的時(shí)候,position會重新回到之前標(biāo)記的postion。

源碼中很容易看出來

mark()


reset()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容