您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java NIO Buffer過程是怎樣的”,在日常操作中,相信很多人在Java NIO Buffer過程是怎樣的問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java NIO Buffer過程是怎樣的”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
前言
在與NIO通道交互時使用Java NIO Buffer。 如您所知,數據從通道讀入緩沖區,并從緩沖區寫入通道。
緩沖區本質上是一個可以寫入數據的內存塊,然后可以再次讀取。 此內存塊包含在NIO Buffer對象中,該對象提供了一組方法,可以更輕松地使用內存塊。
基本緩沖區用法
使用緩沖區讀取和寫入數據通常遵循這4個小步驟:
1.寫入數據到緩沖區
2.調用 buffer.flip()
3.從緩沖區讀取數據
4.調用 buffer.clear() 或者 buffer.compact()
當你將數據寫入Buffer時,Buffer會跟蹤你已經寫入了多少數據。一旦你需要讀出數據,你需要調用 flip() 方法將Buffer從寫模式轉換到讀模式。在讀模式,Buffer允許你將之前寫入的數據全部讀出。
一旦你已經讀出了所有數據,你需要清除Buffer,為下次寫入數據做準備。可以通過以下兩種方法來完成:clear() 和 compact()。clear() 方法清除整個Buffer,而 compact() 方法僅僅清除你已經讀出的Buffer,未讀數據會被移動到Buffer的開始位置,再次寫入的數據會追加到未讀數據的后面。
這是一個簡單的 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的三個屬性:容量,位置和限定符
Buffer本質上是一塊你可以寫入數據的內存區域,當然你也可以在寫入之后讀出數據。該內存區域被封裝成一個 NIO Buffer 對象,它提供一系列的方法,以方便對該內存區域的操作。
為了學習Buffer 是如何工作的,Buffer 的三個屬性你必須要熟悉,它們是:
capacity (容量) position (游標位置) limit (末尾限定符)
其中,position 和 limit 的意義依賴于當前 Buffer 是處于讀模式還是寫模式。capacity 的含義無論讀寫模式都是相同的。
下面是對以上三個屬性在讀模式和寫模式的一個示例,后面會有詳細的解釋:
Buffer capacity, position and limit in write and read mode.
Capacity (容量)
作為一個內存塊,Buffer 有一個固定的大小,我們叫做 “capacity(容量)"。你最多只能向 Buffer 寫入 capacity 大小的字節,長整數,字符等。一旦 Buffer 滿了,你必須在繼續寫入數據之前清空它(讀出數據,或清除數據)。
Position (游標位置)
當你開始向 Buffer 寫入數據時,你必須知道數據將要寫入的位置。position 的初始值為 0。當一個字節或長整數等類似數據類型被寫入 Buffer 后,position 就會指向下一個將要寫入數據的位置(根據數據類型大小計算)。position 的最大值是 capacity - 1。
當你需要從 Buffer 讀出數據時,你也需要知道將要從什么位置開始讀數據。在你調用 flip 方法將 Buffer 從寫模式轉換為讀模式時,position 被重新設置為 0。然后你從 position 指向的位置開始讀取數據,接下來 position 指向下一個你要讀取的位置。
限制(Limit)
在寫模式下對一個Buffer的限制即你能將多少數據寫入Buffer中。在寫模式下,限制等同于Buffer的容量(capacity)。
當切換Buffer為讀模式時,限制表示你最多能讀取到多少數據。因此,當切換Buffer為讀模式時,限制會被設置為寫模式下的position值。換句話說,你能讀到之前寫入的所有數據(限制被設置為已寫的字節數,在寫模式下就是position)。
Buffer類型
Java NIO提出了如下幾種Buffer類型:
ByteBuffer MappedByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer
正如你所看到的,這些Buffer類型代表了不同的數據類型。換句話說,他們讓你可以在使用的時候用char, short, int, long, float 或者double類型來代替直接使用buffer中的字節。
其中MappedByteBuffer有點特殊,將在它自己的部分來闡述。
分配一個Buffer
若要獲取一個Buffer對象,必須先分配它。每個Buffer類都有allocate()函數用來分配。下面的例子展示了分配一個
ByteBuffer,其容量為48字節。
ByteBuffer buf = ByteBuffer.allocate(48);
下面的例子是分配一個具有1024個字符的空間的CharBuffer:
CharBuffer buf = CharBuffer.allocate(1024);
將數據寫入Buffer
有兩種方法可以將數據寫入Buffer:
1.從Channel將數據寫入Buffer
2.調用buffer的put()函數,自己將數據寫入Buffer。
下面的例子是展示Channel如何將數據寫入到Buffer中:
int bytesRead = inChannel.read(buf); //read into buffer.
下面的例子是通過put()函數將數據寫入Buffer:
buf.put(127);
put()函數還有很多其他版本,可以讓你使用不用的方法將數據寫入到Buffer。例如,在特定的位置寫,或者將字節數組寫入到buffer。查看JavaDoc來了解buffer實現的更多細節。
flip()
用 flip() 方法將 Buffer f從寫入模式切換到讀取模式。調用 flip() 將 position 設置回0,并將 limit 置為剛才的位置。
換句話說,position 現在標記了讀取位置,limit 標記了寫入緩沖區的字節、字符數等——可以讀取的字節數、字符數等的限制。
從緩沖區讀取數據
有兩種方法可以從 Buffer 中讀取數據。
1.從緩沖區讀取數據到通道。
2.使用緩沖區自帶方法中的 get() 方法從緩沖區讀取數據。
下面是如何將數據從緩沖區讀取到通道的例子:
//read from buffer into channel.int bytesWritten = inChannel.write(buf);
下面是使用 get() 方法從 Buffer 中讀取數據的例子:
byte aByte = buf.get();
get() 方法還有許多其他版本,允許您以多種不同的方式從 Buffer 中讀取數據。 例如,在特定位置讀取,或者從緩沖區讀取字節數組。有關具體緩沖區實現的詳細信息,請參閱JavaDoc。
rewind()
Buffer.rewind() 將 position 設置回0,因此你可以重讀緩沖區中的所有數據。這個 limit 保持不變,因此仍然標記有多少元素(字節、字符等)可以從Buffer讀取。
clear() and compact()
從 Buffer 中讀取數據之后,必須讓 Buffer 為再次寫入做好準備。您可以通過調用 clear() 或調用 compact()來做到這一點。
如果您調用 clear() ,position 將被設置為0,并 limit 置為 capacity。換句話說,Buffer 被清除。Buffer 中的數據沒有清除。只有標記告訴您可以將數據寫入 Buffer 的位置。
當您調用 clear() 時,如果緩沖區中有任何未讀數據,則數據將被“遺忘”,這意味著您不再有任何標記來說明哪些數據已被讀取,哪些數據未被讀取。
如果 Buffer 中仍然有未讀數據,并且您希望稍后讀取它,但是您需要先寫一些東西,那么調用 compact() 而不是 clear().
compact() 將所有未讀的數據復制到 Buffer 的開頭。然后將 position 設置為最后一個未讀元素之后的位置。與 clear() 一樣,limit 屬性仍然設置為 capacity。現在 Buffer 已經準備好寫入,但是不會覆蓋未讀數據。
mark() and reset()
你可以調用 Buffer.mark() 方法在 Buffer 中標記給定位置。之后,你可以調用 Buffer.reset() 方法重置回標記的這個位置。下面是個例子:
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()方法可以比較兩個緩沖區。
equals()
兩個緩沖相同,如果:
1.他們是同一個類型(byte,char,int等)。
2.在緩沖區,它們遺留有相同量的字節、字符等。
3.所有遺留的字節、字符都相同。
正如你看到的,equals只比較Buffer的一部分,而不是每個元素。事實上,它只比較Buffer中遺留的元素。
compareTo()
用 compareTo() 方法比較兩個緩沖區的遺留元素(字節、字符等),用在例如排序例程。在下列情況中,一個緩沖區被視為“小于”另一個緩沖區,如果:
與另一個緩沖區對應元素相等的第一個元素,小于另一個緩沖區的元素。
所有的元素都相等,但是第一個緩沖區在第二個緩沖區之前耗盡了元素(它有更少的元素)。
到此,關于“Java NIO Buffer過程是怎樣的”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。