在與NIO通道交互時使用Java NIO Buffer。 如您所知,數據從通道讀入緩衝區,並從緩衝區寫入通道。java
緩衝區本質上是一個能夠寫入數據的內存塊,而後能夠再次讀取。 此內存塊包含在NIO Buffer對象中,該對象提供了一組方法,能夠更輕鬆地使用內存塊。數組
基本緩衝區用法app
使用緩衝區讀取和寫入數據一般遵循這4個小步驟:dom
當你將數據寫入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 bytes ByteBuffer buf = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buf); //read into buffer. while (bytesRead != -1) { buf.flip(); //make buffer ready for read while(buf.hasRemaining()){ System.out.print((char) buf.get()); // read 1 byte at a time } buf.clear(); //make buffer ready for writing bytesRead = inChannel.read(buf); } aFile.close();
Buffer的三個屬性:容量,位置和限定符blog
Buffer本質上是一塊你能夠寫入數據的內存區域,固然你也能夠在寫入以後讀出數據。該內存區域被封裝成一個 NIO Buffer 對象,它提供一系列的方法,以方便對該內存區域的操做。排序
爲了學習Buffer 是如何工做的,Buffer 的三個屬性你必需要熟悉,它們是:ip
其中,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類型:
正如你所看到的,這些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:
下面的例子是展現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 中讀取數據。
下面是如何將數據從緩衝區讀取到通道的例子:
//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()方法能夠比較兩個緩衝區。
分享一些知識點給你們但願能幫助到你們,或者從中啓發。
加Q君羊:821169538 都是java愛好者,你們一塊兒討論交流學習
equals()
兩個緩衝相同,若是:
正如你看到的,equals只比較Buffer的一部分,而不是每一個元素。事實上,它只比較Buffer中遺留的元素。
compareTo()
用 compareTo() 方法比較兩個緩衝區的遺留元素(字節、字符等),用在例如排序例程。在下列狀況中,一個緩衝區被視爲「小於」另外一個緩衝區,若是: