溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Java NIO Buffer過(guò)程是怎樣的

發(fā)布時(shí)間:2022-01-11 17:11:21 來(lái)源:億速云 閱讀:147 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹“Java NIO Buffer過(guò)程是怎樣的”,在日常操作中,相信很多人在Java NIO Buffer過(guò)程是怎樣的問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java NIO Buffer過(guò)程是怎樣的”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

前言

在與NIO通道交互時(shí)使用Java NIO Buffer。 如您所知,數(shù)據(jù)從通道讀入緩沖區(qū),并從緩沖區(qū)寫(xiě)入通道。

緩沖區(qū)本質(zhì)上是一個(gè)可以寫(xiě)入數(shù)據(jù)的內(nèi)存塊,然后可以再次讀取。 此內(nèi)存塊包含在NIO Buffer對(duì)象中,該對(duì)象提供了一組方法,可以更輕松地使用內(nèi)存塊。

基本緩沖區(qū)用法

使用緩沖區(qū)讀取和寫(xiě)入數(shù)據(jù)通常遵循這4個(gè)小步驟:

1.寫(xiě)入數(shù)據(jù)到緩沖區(qū)

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

3.從緩沖區(qū)讀取數(shù)據(jù)

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

當(dāng)你將數(shù)據(jù)寫(xiě)入Buffer時(shí),Buffer會(huì)跟蹤你已經(jīng)寫(xiě)入了多少數(shù)據(jù)。一旦你需要讀出數(shù)據(jù),你需要調(diào)用 flip() 方法將Buffer從寫(xiě)模式轉(zhuǎn)換到讀模式。在讀模式,Buffer允許你將之前寫(xiě)入的數(shù)據(jù)全部讀出。

一旦你已經(jīng)讀出了所有數(shù)據(jù),你需要清除Buffer,為下次寫(xiě)入數(shù)據(jù)做準(zhǔn)備??梢酝ㄟ^(guò)以下兩種方法來(lái)完成:clear() 和 compact()。clear() 方法清除整個(gè)Buffer,而 compact() 方法僅僅清除你已經(jīng)讀出的Buffer,未讀數(shù)據(jù)會(huì)被移動(dòng)到Buffer的開(kāi)始位置,再次寫(xiě)入的數(shù)據(jù)會(huì)追加到未讀數(shù)據(jù)的后面。

這是一個(gè)簡(jiǎn)單的 Buffer 使用的例子,使用的 write, flip, read 和 clear 操作:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");FileChannel inChannel = aFile.getChannel();//create buffer with capacity of 48 bytesByteBuffer buf = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buf); //read into buffer.while (bytesRead != -1) { buf.flip(); //make buffer ready for readwhile(buf.hasRemaining()){System.out.print((char) buf.get()); // read 1 byte at a time} buf.clear(); //make buffer ready for writingbytesRead = inChannel.read(buf);}aFile.close();

Buffer的三個(gè)屬性:容量,位置和限定符

Buffer本質(zhì)上是一塊你可以寫(xiě)入數(shù)據(jù)的內(nèi)存區(qū)域,當(dāng)然你也可以在寫(xiě)入之后讀出數(shù)據(jù)。該內(nèi)存區(qū)域被封裝成一個(gè) NIO Buffer 對(duì)象,它提供一系列的方法,以方便對(duì)該內(nèi)存區(qū)域的操作。

為了學(xué)習(xí)Buffer 是如何工作的,Buffer 的三個(gè)屬性你必須要熟悉,它們是:

capacity (容量)  position (游標(biāo)位置)  limit (末尾限定符)

其中,position 和 limit 的意義依賴(lài)于當(dāng)前 Buffer 是處于讀模式還是寫(xiě)模式。capacity 的含義無(wú)論讀寫(xiě)模式都是相同的。

下面是對(duì)以上三個(gè)屬性在讀模式和寫(xiě)模式的一個(gè)示例,后面會(huì)有詳細(xì)的解釋?zhuān)?/p>

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

Capacity (容量)

作為一個(gè)內(nèi)存塊,Buffer 有一個(gè)固定的大小,我們叫做 “capacity(容量)"。你最多只能向 Buffer 寫(xiě)入 capacity 大小的字節(jié),長(zhǎng)整數(shù),字符等。一旦 Buffer 滿(mǎn)了,你必須在繼續(xù)寫(xiě)入數(shù)據(jù)之前清空它(讀出數(shù)據(jù),或清除數(shù)據(jù))。

Position (游標(biāo)位置)

當(dāng)你開(kāi)始向 Buffer 寫(xiě)入數(shù)據(jù)時(shí),你必須知道數(shù)據(jù)將要寫(xiě)入的位置。position 的初始值為 0。當(dāng)一個(gè)字節(jié)或長(zhǎng)整數(shù)等類(lèi)似數(shù)據(jù)類(lèi)型被寫(xiě)入 Buffer 后,position 就會(huì)指向下一個(gè)將要寫(xiě)入數(shù)據(jù)的位置(根據(jù)數(shù)據(jù)類(lèi)型大小計(jì)算)。position 的最大值是 capacity - 1。

當(dāng)你需要從 Buffer 讀出數(shù)據(jù)時(shí),你也需要知道將要從什么位置開(kāi)始讀數(shù)據(jù)。在你調(diào)用 flip 方法將 Buffer 從寫(xiě)模式轉(zhuǎn)換為讀模式時(shí),position 被重新設(shè)置為 0。然后你從 position 指向的位置開(kāi)始讀取數(shù)據(jù),接下來(lái) position 指向下一個(gè)你要讀取的位置。

限制(Limit)

在寫(xiě)模式下對(duì)一個(gè)Buffer的限制即你能將多少數(shù)據(jù)寫(xiě)入Buffer中。在寫(xiě)模式下,限制等同于Buffer的容量(capacity)。

當(dāng)切換Buffer為讀模式時(shí),限制表示你最多能讀取到多少數(shù)據(jù)。因此,當(dāng)切換Buffer為讀模式時(shí),限制會(huì)被設(shè)置為寫(xiě)模式下的position值。換句話說(shuō),你能讀到之前寫(xiě)入的所有數(shù)據(jù)(限制被設(shè)置為已寫(xiě)的字節(jié)數(shù),在寫(xiě)模式下就是position)。

Buffer類(lèi)型

Java NIO提出了如下幾種Buffer類(lèi)型:

ByteBuffer  MappedByteBuffer  CharBuffer  DoubleBuffer  FloatBuffer  IntBuffer  LongBuffer  ShortBuffer

正如你所看到的,這些Buffer類(lèi)型代表了不同的數(shù)據(jù)類(lèi)型。換句話說(shuō),他們讓你可以在使用的時(shí)候用char, short, int, long, float 或者double類(lèi)型來(lái)代替直接使用buffer中的字節(jié)。

其中MappedByteBuffer有點(diǎn)特殊,將在它自己的部分來(lái)闡述。

分配一個(gè)Buffer

若要獲取一個(gè)Buffer對(duì)象,必須先分配它。每個(gè)Buffer類(lèi)都有allocate()函數(shù)用來(lái)分配。下面的例子展示了分配一個(gè)

ByteBuffer,其容量為48字節(jié)。

ByteBuffer buf = ByteBuffer.allocate(48);

下面的例子是分配一個(gè)具有1024個(gè)字符的空間的CharBuffer:

CharBuffer buf = CharBuffer.allocate(1024);

將數(shù)據(jù)寫(xiě)入Buffer

有兩種方法可以將數(shù)據(jù)寫(xiě)入Buffer:

1.從Channel將數(shù)據(jù)寫(xiě)入Buffer

2.調(diào)用buffer的put()函數(shù),自己將數(shù)據(jù)寫(xiě)入Buffer。

下面的例子是展示Channel如何將數(shù)據(jù)寫(xiě)入到Buffer中:

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

下面的例子是通過(guò)put()函數(shù)將數(shù)據(jù)寫(xiě)入Buffer:

buf.put(127);

put()函數(shù)還有很多其他版本,可以讓你使用不用的方法將數(shù)據(jù)寫(xiě)入到Buffer。例如,在特定的位置寫(xiě),或者將字節(jié)數(shù)組寫(xiě)入到buffer。查看JavaDoc來(lái)了解buffer實(shí)現(xiàn)的更多細(xì)節(jié)。

flip()

用 flip() 方法將 Buffer f從寫(xiě)入模式切換到讀取模式。調(diào)用 flip() 將 position 設(shè)置回0,并將 limit 置為剛才的位置。

換句話說(shuō),position 現(xiàn)在標(biāo)記了讀取位置,limit 標(biāo)記了寫(xiě)入緩沖區(qū)的字節(jié)、字符數(shù)等——可以讀取的字節(jié)數(shù)、字符數(shù)等的限制。

從緩沖區(qū)讀取數(shù)據(jù)

有兩種方法可以從 Buffer 中讀取數(shù)據(jù)。

1.從緩沖區(qū)讀取數(shù)據(jù)到通道。

2.使用緩沖區(qū)自帶方法中的 get() 方法從緩沖區(qū)讀取數(shù)據(jù)。

下面是如何將數(shù)據(jù)從緩沖區(qū)讀取到通道的例子:

//read from buffer into channel.int bytesWritten = inChannel.write(buf);

下面是使用 get() 方法從 Buffer 中讀取數(shù)據(jù)的例子:

byte aByte = buf.get();

get() 方法還有許多其他版本,允許您以多種不同的方式從 Buffer 中讀取數(shù)據(jù)。 例如,在特定位置讀取,或者從緩沖區(qū)讀取字節(jié)數(shù)組。有關(guān)具體緩沖區(qū)實(shí)現(xiàn)的詳細(xì)信息,請(qǐng)參閱JavaDoc。

rewind()

Buffer.rewind() 將 position 設(shè)置回0,因此你可以重讀緩沖區(qū)中的所有數(shù)據(jù)。這個(gè) limit 保持不變,因此仍然標(biāo)記有多少元素(字節(jié)、字符等)可以從Buffer讀取。

clear() and compact()

從 Buffer 中讀取數(shù)據(jù)之后,必須讓 Buffer 為再次寫(xiě)入做好準(zhǔn)備。您可以通過(guò)調(diào)用 clear() 或調(diào)用 compact()來(lái)做到這一點(diǎn)。

如果您調(diào)用 clear() ,position 將被設(shè)置為0,并 limit 置為 capacity。換句話說(shuō),Buffer 被清除。Buffer 中的數(shù)據(jù)沒(méi)有清除。只有標(biāo)記告訴您可以將數(shù)據(jù)寫(xiě)入 Buffer 的位置。

當(dāng)您調(diào)用 clear() 時(shí),如果緩沖區(qū)中有任何未讀數(shù)據(jù),則數(shù)據(jù)將被“遺忘”,這意味著您不再有任何標(biāo)記來(lái)說(shuō)明哪些數(shù)據(jù)已被讀取,哪些數(shù)據(jù)未被讀取。

如果 Buffer 中仍然有未讀數(shù)據(jù),并且您希望稍后讀取它,但是您需要先寫(xiě)一些東西,那么調(diào)用 compact() 而不是 clear().

compact() 將所有未讀的數(shù)據(jù)復(fù)制到 Buffer 的開(kāi)頭。然后將 position 設(shè)置為最后一個(gè)未讀元素之后的位置。與 clear() 一樣,limit 屬性仍然設(shè)置為 capacity?,F(xiàn)在 Buffer 已經(jīng)準(zhǔn)備好寫(xiě)入,但是不會(huì)覆蓋未讀數(shù)據(jù)。

mark() and reset()

你可以調(diào)用 Buffer.mark() 方法在 Buffer 中標(biāo)記給定位置。之后,你可以調(diào)用 Buffer.reset() 方法重置回標(biāo)記的這個(gè)位置。下面是個(gè)例子:

buffer.mark();//call buffer.get() a couple of times, e.g. during parsing.buffer.reset(); //set position back to mark.

equals() and compareTo()

用equals() 和 compareTo()方法可以比較兩個(gè)緩沖區(qū)。

equals()

兩個(gè)緩沖相同,如果:

1.他們是同一個(gè)類(lèi)型(byte,char,int等)。

2.在緩沖區(qū),它們遺留有相同量的字節(jié)、字符等。

3.所有遺留的字節(jié)、字符都相同。

正如你看到的,equals只比較Buffer的一部分,而不是每個(gè)元素。事實(shí)上,它只比較Buffer中遺留的元素。

compareTo()

用 compareTo() 方法比較兩個(gè)緩沖區(qū)的遺留元素(字節(jié)、字符等),用在例如排序例程。在下列情況中,一個(gè)緩沖區(qū)被視為“小于”另一個(gè)緩沖區(qū),如果:

與另一個(gè)緩沖區(qū)對(duì)應(yīng)元素相等的第一個(gè)元素,小于另一個(gè)緩沖區(qū)的元素。

所有的元素都相等,但是第一個(gè)緩沖區(qū)在第二個(gè)緩沖區(qū)之前耗盡了元素(它有更少的元素)。

到此,關(guān)于“Java NIO Buffer過(guò)程是怎樣的”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI