JAVA-NIO之Buffer

Java NIO中的Buffer用于和NIO通道進行交互。如你所知,數(shù)據(jù)是從通道讀入緩沖區(qū)骚烧,從緩沖區(qū)寫入到通道中的顶瞒。
緩沖區(qū)本質(zhì)上是一塊可以寫入數(shù)據(jù)夸政,然后可以從中讀取數(shù)據(jù)的內(nèi)存。這塊內(nèi)存被包裝成NIO Buffer對象榴徐,并提供了一組方法守问,用來方便的訪問該塊內(nèi)存。

Buffer的基本用法

寫入數(shù)據(jù)到Buffer
調(diào)用flip()方法
從Buffer中讀取數(shù)據(jù)
調(diào)用clear()方法或者compact()方法

當(dāng)向buffer寫入數(shù)據(jù)時坑资,buffer會記錄下寫了多少數(shù)據(jù)酪碘。一旦要讀取數(shù)據(jù),需要通過flip()方法將Buffer從寫模式切換到讀模式盐茎。在讀模式下兴垦,可以讀取之前寫入到buffer的所有數(shù)據(jù)。
一旦讀完了所有的數(shù)據(jù),就需要清空緩沖區(qū)探越,讓它可以再次被寫入狡赐。有兩種方式能清空緩沖區(qū):調(diào)用clear()或compact()方法。clear()方法會清空整個緩沖區(qū)钦幔。compact()方法只會清除已經(jīng)讀過的數(shù)據(jù)枕屉。任何未讀的數(shù)據(jù)都被移到緩沖區(qū)的起始處,新寫入的數(shù)據(jù)將放到緩沖區(qū)未讀數(shù)據(jù)的后面鲤氢。

下面是一個使用Buffer的例子:

Buffer的capacity,position和limit

緩沖區(qū)本質(zhì)上是一塊可以寫入數(shù)據(jù)搀擂,然后可以從中讀取數(shù)據(jù)的內(nèi)存。這塊內(nèi)存被包裝成NIO Buffer對象卷玉,并提供了一組方法哨颂,用來方便的訪問該塊內(nèi)存。
為了理解Buffer的工作原理相种,需要熟悉它的三個屬性:
capacity
position
limit

position和limit的含義取決于Buffer處在讀模式還是寫模式威恼。不管Buffer處在什么模式,capacity的含義總是一樣的寝并。
這里有一個關(guān)于capacity箫措,position和limit在讀寫模式中的說明,詳細(xì)的解釋在插圖后面衬潦。


capacity

作為一個內(nèi)存塊斤蔓,Buffer有一個固定的大小值,也叫“capacity”.你只能往里寫capacity個byte镀岛、long附迷,char等類型。一旦Buffer滿了哎媚,需要將其清空(通過讀數(shù)據(jù)或者清除數(shù)據(jù))才能繼續(xù)寫數(shù)據(jù)往里寫數(shù)據(jù)喇伯。

position

當(dāng)你寫數(shù)據(jù)到Buffer中時,position表示當(dāng)前的位置拨与。初始的position值為0.當(dāng)一個byte割捅、long等數(shù)據(jù)寫到Buffer后蕾域, position會向前移動到下一個可插入數(shù)據(jù)的Buffer單元宙橱。position最大可為capacity – 1.
當(dāng)讀取數(shù)據(jù)時憔杨,也是從某個特定位置讀。當(dāng)將Buffer從寫模式切換到讀模式淤毛,position會被重置為0. 當(dāng)從Buffer的position處讀取數(shù)據(jù)時今缚,position向前移動到下一個可讀的位置。

limit

在寫模式下低淡,Buffer的limit表示你最多能往Buffer里寫多少數(shù)據(jù)姓言。 寫模式下瞬项,limit等于Buffer的capacity。
當(dāng)切換Buffer到讀模式時何荚, limit表示你最多能讀到多少數(shù)據(jù)囱淋。因此,當(dāng)切換Buffer到讀模式時餐塘,limit會被設(shè)置成寫模式下的position值妥衣。換句話說,你能讀到之前寫入的所有數(shù)據(jù)(limit被設(shè)置成已寫數(shù)據(jù)的數(shù)量戒傻,這個值在寫模式下就是position)

Buffer的類型

Java NIO 有以下Buffer類型
ByteBuffer
MappedByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer

如你所見税手,這些Buffer類型代表了不同的數(shù)據(jù)類型。換句話說需纳,就是可以通過char芦倒,short,int候齿,long,float 或 double類型來操作緩沖區(qū)中的字節(jié)闺属。
MappedByteBuffer 有些特別慌盯,在涉及它的專門章節(jié)中再講。

Buffer的分配

要想獲得一個Buffer對象首先要進行分配掂器。 每一個Buffer類都有一個allocate方法亚皂。
下面是一個分配48字節(jié)capacity的ByteBuffer的例子。
ByteBuffer buf = ByteBuffer.allocate(48);
這是分配一個可存儲1024個字符的CharBuffer:
CharBuffer buf = CharBuffer.allocate(1024);

向Buffer中寫數(shù)據(jù)

寫數(shù)據(jù)到Buffer有兩種方式:
從Channel寫到Buffer国瓮。
通過Buffer的put()方法寫到Buffer里灭必。
從Channel寫到Buffer的例子
int bytesRead = inChannel.read(buf);
//read into buffer.
通過put方法寫B(tài)uffer的例子:
buf.put(127);
put方法有很多版本,允許你以不同的方式把數(shù)據(jù)寫入到Buffer中乃摹。例如禁漓, 寫到一個指定的位置,或者把一個字節(jié)數(shù)組寫入到Buffer孵睬。 更多Buffer實現(xiàn)的細(xì)節(jié)參考JavaDoc播歼。

flip()方法

flip方法將Buffer從寫模式切換到讀模式。調(diào)用flip()方法會將position設(shè)回0掰读,并將limit設(shè)置成之前position的值秘狞。
換句話說,position現(xiàn)在用于標(biāo)記讀的位置蹈集,limit表示之前寫進了多少個byte烁试、char等 —— 現(xiàn)在能讀取多少個byte、char等拢肆。

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

從Buffer中讀取數(shù)據(jù)有兩種方式:
從Buffer讀取數(shù)據(jù)到Channel减响。
使用get()方法從Buffer中讀取數(shù)據(jù)靖诗。

從Buffer讀取數(shù)據(jù)到Channel的例子
//read from buffer into channel.
int bytesWritten = inChannel.write(buf);
使用get()方法從Buffer中讀取數(shù)據(jù)的例子
byte aByte = buf.get();
get方法有很多版本,允許你以不同的方式從Buffer中讀取數(shù)據(jù)辩蛋。例如呻畸,從指定position讀取,或者從Buffer中讀取數(shù)據(jù)到字節(jié)數(shù)組悼院。更多Buffer實現(xiàn)的細(xì)節(jié)參考JavaDoc伤为。

rewind()方法

Buffer.rewind()將position設(shè)回0,所以你可以重讀Buffer中的所有數(shù)據(jù)据途。limit保持不變绞愚,仍然表示能從Buffer中讀取多少個元素(byte、char等)颖医。

clear()與compact()方法

一旦讀完Buffer中的數(shù)據(jù)位衩,需要讓Buffer準(zhǔn)備好再次被寫入∪巯簦可以通過clear()或compact()方法來完成糖驴。
如果調(diào)用的是clear()方法,position將被設(shè)回0佛致,limit被設(shè)置成 capacity的值贮缕。換句話說,Buffer 被清空了俺榆。Buffer中的數(shù)據(jù)并未清除感昼,只是這些標(biāo)記告訴我們可以從哪里開始往Buffer里寫數(shù)據(jù)。
如果Buffer中有一些未讀的數(shù)據(jù)罐脊,調(diào)用clear()方法定嗓,數(shù)據(jù)將“被遺忘”,意味著不再有任何標(biāo)記會告訴你哪些數(shù)據(jù)被讀過萍桌,哪些還沒有宵溅。
如果Buffer中仍有未讀的數(shù)據(jù),且后續(xù)還需要這些數(shù)據(jù)上炎,但是此時想要先先寫些數(shù)據(jù)层玲,那么使用compact()方法。
compact()方法將所有未讀的數(shù)據(jù)拷貝到Buffer起始處反症。然后將position設(shè)到最后一個未讀元素正后面辛块。limit屬性依然像clear()方法一樣,設(shè)置成capacity∏Π現(xiàn)在Buffer準(zhǔn)備好寫數(shù)據(jù)了润绵,但是不會覆蓋未讀的數(shù)據(jù)。

mark()與reset()方法

通過調(diào)用Buffer.mark()方法胞谈,可以標(biāo)記Buffer中的一個特定position尘盼。之后可以通過調(diào)用Buffer.reset()方法恢復(fù)到這個position憨愉。例如:
buffer.mark();
//call buffer.get() a couple of times, e.g. during parsing.
buffer.reset();
//set position back to mark.

equals()與compareTo()方法

可以使用equals()和compareTo()方法兩個Buffer。

equals()

當(dāng)滿足下列條件時卿捎,表示兩個Buffer相等:
有相同的類型(byte配紫、char、int等)午阵。
Buffer中剩余的byte躺孝、char等的個數(shù)相等。
Buffer中所有剩余的byte底桂、char等都相同植袍。

如你所見,equals只是比較Buffer的一部分籽懦,不是每一個在它里面的元素都比較于个。實際上,它只比較Buffer中的剩余元素暮顺。

compareTo()方法

compareTo()方法比較兩個Buffer的剩余元素(byte厅篓、char等), 如果滿足下列條件捶码,則認(rèn)為一個Buffer“小于”另一個Buffer:
第一個不相等的元素小于另一個Buffer中對應(yīng)的元素 羽氮。
所有元素都相等,但第一個Buffer比另一個先耗盡(第一個Buffer的元素個數(shù)比另一個少)宙项。

(譯注:剩余元素是從 position到limit之間的元素)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乏苦,一起剝皮案震驚了整個濱河市株扛,隨后出現(xiàn)的幾起案子尤筐,更是在濱河造成了極大的恐慌,老刑警劉巖洞就,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盆繁,死亡現(xiàn)場離奇詭異,居然都是意外死亡旬蟋,警方通過查閱死者的電腦和手機油昂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倾贰,“玉大人冕碟,你說我怎么就攤上這事〈艺悖” “怎么了安寺?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長首尼。 經(jīng)常有香客問我挑庶,道長言秸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任迎捺,我火速辦了婚禮举畸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凳枝。我一直安慰自己抄沮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布范舀。 她就那樣靜靜地躺著合是,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锭环。 梳的紋絲不亂的頭發(fā)上聪全,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音辅辩,去河邊找鬼难礼。 笑死,一個胖子當(dāng)著我的面吹牛玫锋,可吹牛的內(nèi)容都是我干的蛾茉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼撩鹿,長吁一口氣:“原來是場噩夢啊……” “哼谦炬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起节沦,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤键思,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后甫贯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吼鳞,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年叫搁,在試婚紗的時候發(fā)現(xiàn)自己被綠了赔桌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡渴逻,死狀恐怖疾党,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惨奕,我是刑警寧澤雪位,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站墓贿,受9級特大地震影響茧泪,放射性物質(zhì)發(fā)生泄漏蜓氨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一队伟、第九天 我趴在偏房一處隱蔽的房頂上張望穴吹。 院中可真熱鬧,春花似錦嗜侮、人聲如沸港令。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顷霹。三九已至,卻和暖如春击吱,著一層夾襖步出監(jiān)牢的瞬間淋淀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工覆醇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朵纷,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓永脓,卻偏偏與公主長得像袍辞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子常摧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自 http://www.ibm.com/developerworks/cn/education/java/j-...
    抓兔子的貓閱讀 2,290評論 0 22
  • Java NIO(New IO)是從Java 1.4版本開始引入的一個新的IO API搅吁,可以替代標(biāo)準(zhǔn)的Java I...
    JackChen1024閱讀 7,546評論 1 143
  • Java NIO中的Buffer用于和NIO通道進行交互。如你所知落午,數(shù)據(jù)是從通道讀入緩沖區(qū)谎懦,從緩沖區(qū)寫入到通道中的...
    AFinalStone閱讀 276評論 0 0
  • (轉(zhuǎn)載說明:本文非原創(chuàng)党瓮,轉(zhuǎn)載自http://ifeve.com/java-nio-all/) Java NIO: ...
    柳岸閱讀 814評論 0 3
  • 二十多歲的日子 我深知自己有許多的壞毛病详炬。沒耐心盐类,沒毅力,還伴隨著懶散呛谜。至于優(yōu)點在跳,與同齡人相比,我并沒有拿得出手的...
    行走的阿木閱讀 293評論 0 0