(2)NIO 之 Buffer(緩沖區(qū))

一 Buffer(緩沖區(qū))介紹

1.1Buffer本質(zhì)上就是一塊內(nèi)存區(qū),可以用來(lái)寫(xiě)入數(shù)據(jù)章咧,并在稍后讀取出來(lái)倦西。這塊內(nèi)存被NIO Buffer包裹起來(lái),對(duì)外提供一系列的讀寫(xiě)方便開(kāi)發(fā)的接口赁严。

在Java NIO中使用的核心緩沖區(qū)如下(覆蓋了通過(guò)I/O發(fā)送的基本數(shù)據(jù)類型:byte, char扰柠、short, int, long, float, double ,long):

ByteBuffer

CharBuffer

ShortBuffer

IntBuffer

FloatBuffer

DoubleBuffer

LongBuffer

1.2利用Buffer讀寫(xiě)數(shù)據(jù)疼约,通常遵循四個(gè)步驟

把數(shù)據(jù)寫(xiě)入buffer卤档;

調(diào)用flip;

從Buffer中讀取數(shù)據(jù)程剥;

調(diào)用buffer.clear()或者buffer.compact()劝枣。

當(dāng)寫(xiě)入數(shù)據(jù)到buffer中時(shí),buffer會(huì)記錄已經(jīng)寫(xiě)入的數(shù)據(jù)大小。當(dāng)需要讀數(shù)據(jù)時(shí)舔腾,通過(guò)flip()方法把buffer從寫(xiě)模式調(diào)整為讀模式溪胶;在讀模式下,可以讀取所有已經(jīng)寫(xiě)入的數(shù)據(jù)稳诚。

當(dāng)讀取完數(shù)據(jù)后哗脖,需要清空buffer,以滿足后續(xù)寫(xiě)入操作扳还。清空buffer有兩種方式:調(diào)用clear()compact()方法才避。clear會(huì)清空整個(gè)buffer,compact則只清空已讀取的數(shù)據(jù)氨距,未被讀取的數(shù)據(jù)會(huì)被移動(dòng)到buffer的開(kāi)始位置桑逝,寫(xiě)入位置則近跟著未讀數(shù)據(jù)之后。

1.3Buffer的容量衔蹲,位置肢娘,上限(Buffer Capacity, Position and Limit)

這塊內(nèi)存被NIO Buffer管理,并提供一系列的方法用于更簡(jiǎn)單的操作這塊內(nèi)存舆驶。

一個(gè)Buffer有三個(gè)屬性是必須掌握的橱健,分別是:

capacity容量??position位置??limit限制

position和limit的具體含義取決于當(dāng)前buffer模式。capacity在兩種模式下都表示容量沙廉。

讀寫(xiě)模式下position和limit的含義:

容量(Capacity)

作為一塊內(nèi)存拘荡,buffer有一個(gè)固定的大小,叫做capacit(容量)撬陵。也就是最多只能寫(xiě)入容量值得字節(jié)珊皿,整形等數(shù)據(jù)。一旦buffer寫(xiě)滿了就需要清空已讀數(shù)據(jù)以便下次繼續(xù)寫(xiě)入新的數(shù)據(jù)巨税。

位置(Position)

當(dāng)寫(xiě)入數(shù)據(jù)到Buffer的時(shí)候需要從一個(gè)確定的位置開(kāi)始蟋定,默認(rèn)初始化時(shí)這個(gè)位置position為0,一旦寫(xiě)入了數(shù)據(jù)比如一個(gè)字節(jié)草添,整形數(shù)據(jù)驶兜,那么position的值就會(huì)指向數(shù)據(jù)之后的一個(gè)單元,position最大可以到capacity-1.

當(dāng)從Buffer讀取數(shù)據(jù)時(shí)远寸,也需要從一個(gè)確定的位置開(kāi)始抄淑。buffer從寫(xiě)入模式變?yōu)樽x取模式時(shí),position會(huì)歸零驰后,每次讀取后肆资,position向后移動(dòng)。

上限(Limit)

在寫(xiě)模式灶芝,limit的含義是我們所能寫(xiě)入的最大數(shù)據(jù)量郑原,它等同于buffer的容量唉韭。

一旦切換到讀模式,limit則代表我們所能讀取的最大數(shù)據(jù)量犯犁,他的值等同于寫(xiě)模式下position的位置纽哥。換句話說(shuō),您可以讀取與寫(xiě)入數(shù)量相同的字節(jié)數(shù)(限制設(shè)置為寫(xiě)入的字節(jié)數(shù)栖秕,由位置標(biāo)記)。

二 Buffer的常見(jiàn)方法

方法介紹

abstract Object array()返回支持此緩沖區(qū)的數(shù)組 (可選操作)

abstract int arrayOffset()返回該緩沖區(qū)的緩沖區(qū)的第一個(gè)元素的在數(shù)組中的偏移量 (可選操作)

int capacity()返回此緩沖區(qū)的容量

Buffer clear()清除此緩存區(qū)晓避。將position = 0;limit = capacity;mark = -1;

Buffer flip()flip()方法可以吧Buffer從寫(xiě)模式切換到讀模式簇捍。調(diào)用flip方法會(huì)把position歸零,并設(shè)置limit為之前的position的值俏拱。 也就是說(shuō)暑塑,現(xiàn)在position代表的是讀取位置,limit標(biāo)示的是已寫(xiě)入的數(shù)據(jù)位置锅必。

abstract boolean hasArray()告訴這個(gè)緩沖區(qū)是否由可訪問(wèn)的數(shù)組支持

boolean hasRemaining()return position < limit事格,返回是否還有未讀內(nèi)容

abstract boolean isDirect()判斷個(gè)緩沖區(qū)是否為 direct

abstract boolean isReadOnly()判斷告知這個(gè)緩沖區(qū)是否是只讀的

int limit()返回此緩沖區(qū)的限制

Buffer position(int newPosition)設(shè)置這個(gè)緩沖區(qū)的位置

int remaining()return limit - position; 返回limit和position之間相對(duì)位置差

Buffer rewind()把position設(shè)為0,mark設(shè)為-1搞隐,不改變limit的值

Buffer mark()將此緩沖區(qū)的標(biāo)記設(shè)置在其位置

三 Buffer的使用方式/方法介紹

3.1分配緩沖區(qū)(Allocating a Buffer)

為了獲得緩沖區(qū)對(duì)象驹愚,我們必須首先分配一個(gè)緩沖區(qū)。在每個(gè)Buffer類中劣纲,allocate()方法用于分配緩沖區(qū)逢捺。

下面來(lái)看看ByteBuffer分配容量為28字節(jié)的例子:

ByteBuffer buf = ByteBuffer.allocate(28);

下面來(lái)看看另一個(gè)示例:CharBuffer分配空間大小為2048個(gè)字符。

CharBuffer buf = CharBuffer.allocate(2048);

3.2寫(xiě)入數(shù)據(jù)到緩沖區(qū)(Writing Data to a Buffer)

寫(xiě)數(shù)據(jù)到Buffer有兩種方法:

從Channel中寫(xiě)數(shù)據(jù)到Buffer

手動(dòng)寫(xiě)數(shù)據(jù)到Buffer癞季,調(diào)用put方法

下面是一個(gè)實(shí)例劫瞳,演示從Channel寫(xiě)數(shù)據(jù)到Buffer:

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

通過(guò)put寫(xiě)數(shù)據(jù):

buf.put(127);

put方法有很多不同版本,對(duì)應(yīng)不同的寫(xiě)數(shù)據(jù)方法绷柒。例如把數(shù)據(jù)寫(xiě)到特定的位置志于,或者把一個(gè)字節(jié)數(shù)據(jù)寫(xiě)入buffer》夏溃看考JavaDoc文檔可以查閱的更多數(shù)據(jù)伺绽。

3.3翻轉(zhuǎn)(flip())

flip()方法可以吧Buffer從寫(xiě)模式切換到讀模式。調(diào)用flip方法會(huì)把position歸零郊楣,并設(shè)置limit為之前的position的值憔恳。 也就是說(shuō),現(xiàn)在position代表的是讀取位置净蚤,limit標(biāo)示的是已寫(xiě)入的數(shù)據(jù)位置钥组。

從Buffer讀取數(shù)據(jù)(Reading Data from a Buffer)

3.4從Buffer讀數(shù)據(jù)也有兩種方式:

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

從buffer直接讀取數(shù)據(jù),調(diào)用get方法

讀取數(shù)據(jù)到channel的例子:

int bytesWritten = inChannel.write(buf);

調(diào)用get讀取數(shù)據(jù)的例子:

byte aByte = buf.get();

get也有諸多版本今瀑,對(duì)應(yīng)了不同的讀取方式程梦。

3.5 rewind()

Buffer.rewind()方法將position置為0点把,這樣我們可以重復(fù)讀取buffer中的數(shù)據(jù)。limit保持不變屿附。

3.6 clear() and compact()

一旦我們從buffer中讀取完數(shù)據(jù)郎逃,需要復(fù)用buffer為下次寫(xiě)數(shù)據(jù)做準(zhǔn)備。只需要調(diào)用clear()或compact()方法挺份。

如果調(diào)用的是clear()方法褒翰,position將被設(shè)回0,limit被設(shè)置成 capacity的值匀泊。換句話說(shuō)优训,Buffer 被清空了。Buffer中的數(shù)據(jù)并未清除各聘,只是這些標(biāo)記告訴我們可以從哪里開(kāi)始往Buffer里寫(xiě)數(shù)據(jù)揣非。

如果Buffer還有一些數(shù)據(jù)沒(méi)有讀取完,調(diào)用clear就會(huì)導(dǎo)致這部分?jǐn)?shù)據(jù)被“遺忘”躲因,因?yàn)槲覀儧](méi)有標(biāo)記這部分?jǐn)?shù)據(jù)未讀早敬。

針對(duì)這種情況,如果需要保留未讀數(shù)據(jù)大脉,那么可以使用compact搞监。 因此compact()clear()的區(qū)別就在于:對(duì)未讀數(shù)據(jù)的處理,是保留這部分?jǐn)?shù)據(jù)還是一起清空箱靴。

3.7 mark()與reset()方法

通過(guò)調(diào)用Buffer.mark()方法腺逛,可以標(biāo)記Buffer中的一個(gè)特定position。之后可以通過(guò)調(diào)用Buffer.reset()方法恢復(fù)到這個(gè)position衡怀。例如:

buffer.mark();

//call buffer.get() a couple of times, e.g. during parsing.

buffer.reset(); ?//set position back to mark. ? ?

3.8 equals() and compareTo()

可以用eqauls和compareTo比較兩個(gè)buffer

equals():

判斷兩個(gè)buffer相對(duì)棍矛,需滿足:類型相同

buffer中剩余字節(jié)數(shù)相同,所有剩余字節(jié)相等

從上面的三個(gè)條件可以看出,equals只比較buffer中的部分內(nèi)容抛杨,并不會(huì)去比較每一個(gè)元素够委。

compareTo():

compareTo也是比較buffer中的剩余元素,只不過(guò)這個(gè)方法適用于比較排序的:

四 Buffer常用方法測(cè)試

這里以ByteBuffer為例子說(shuō)明抽象類Buffer的實(shí)現(xiàn)類的一些常見(jiàn)方法的使用:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怖现,一起剝皮案震驚了整個(gè)濱河市茁帽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屈嗤,老刑警劉巖潘拨,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異饶号,居然都是意外死亡铁追,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)茫船,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)琅束,“玉大人扭屁,你說(shuō)我怎么就攤上這事∩鳎” “怎么了料滥?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)艾船。 經(jīng)常有香客問(wèn)我葵腹,道長(zhǎng),這世上最難降的妖魔是什么屿岂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任礁蔗,我火速辦了婚禮,結(jié)果婚禮上雁社,老公的妹妹穿的比我還像新娘。我一直安慰自己晒骇,他們只是感情好霉撵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著洪囤,像睡著了一般徒坡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘤缩,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天喇完,我揣著相機(jī)與錄音,去河邊找鬼剥啤。 笑死锦溪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的府怯。 我是一名探鬼主播刻诊,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼牺丙!你這毒婦竟也來(lái)了则涯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤冲簿,失蹤者是張志新(化名)和其女友劉穎粟判,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體峦剔,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡档礁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了羊异。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片事秀。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彤断,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出易迹,到底是詐尸還是另有隱情宰衙,我是刑警寧澤所刀,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布沥阱,位于F島的核電站,受9級(jí)特大地震影響涨薪,放射性物質(zhì)發(fā)生泄漏窘疮。R本人自食惡果不足惜袋哼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闸衫。 院中可真熱鬧涛贯,春花似錦、人聲如沸蔚出。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骄酗。三九已至稀余,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間趋翻,已是汗流浹背睛琳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踏烙,地道東北人师骗。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像讨惩,于是被迫代替她去往敵國(guó)和親丧凤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354