1、前言
熟悉NIO的人想必必定不會陌生buffer中position,limit,capacity這三個屬性吧,以前在學習的時候遇到一個問題:就是當你先往緩衝區寫入一部分數據,而後調用flip()方法,再所有讀取完數據,而後再調用flip()方法,此時這三個值的變化是怎樣的,研究了一下,決定寫下來分享一下。java
2、正文
一、介紹數組
position: 它指的是下一次讀取或寫入的位置。學習
limit: 指定還有多少數據須要寫出(在從緩衝區寫入通道時),或者還有多少空間能夠讀入數據(在從通道讀入緩衝區時),它初始化是與capacity的值同樣,當調用flip()方法以後,它的值會改變成position的值,而position被置0。它箭頭所指的位置是最後一位元素的下一位所在的位置*測試
capacity: 指定了能夠存儲在緩衝區中的最大數據容量,實際上,它指定了底層數組的大小,或者至少是指定了准許咱們使用的底層數組的容量,這個初始化後就不會再改變了。大數據
二、圖示this
以上三個屬性值之間有一些相對大小的關係:0 <= position <= limit <= capacity。若是咱們建立一個新的容量大小爲7的ByteBuffer對象,在初始化的時候,position設置爲0,limit和 capacity被設置爲7,在之後使用ByteBuffer對象過程當中,capacity的值不會再發生變化,而其它兩個個將會隨着使用而變化。三個屬性值分別如圖所示:spa
初始化:3d
假設咱們如今要往這個緩衝區裏面寫入3個字節,寫完以後,position的箭頭就會指向3的位置,而limit不變:code
此時咱們想從緩衝區讀取這3個字節,就必須調用flip()方法,調用了flip()方法事後,limit置爲position的位置,而position被置爲0,也正應證了上面所說的,position它指的是下一次讀取或寫入的位置,limit它箭頭所指的位置是最後一位元素的下一位所在的位置:對象
如今咱們能夠調用get()方法,一直從緩衝區裏面取數據,直到取完爲止,也就是當position與limit的值同樣時,就取完了:
這一次簡單的讀寫操做就完成了,若是想恢復成初始狀態的話,能夠調用clear()方法:
以前學到這裏的時候有個疑問,不知道你們想過沒有,就是咱們在調用了get()方法從緩衝區取完裏面的數據,立馬去調用flip()方法,那這三個屬性的值會是什麼變化?若是當我只讀了2個字節的數據以後,就不讀了,而後再去調用flip(),這三個值又會是怎麼變化?其實無論怎麼繞,你只要懂得原理,就不難,我們先看flip()源代碼作了什麼:
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
這裏不難發現,調用flip()方法,無非就是給這幾個變量賦值,將當前的position值賦給limit,而後將position的值置爲0,Mark是一個標誌變量,我們之後會提到。熟悉以上代碼就不難解決我提出的2個問題:
當你讀取完調用flip()的方法 positon:0 limit:3 capacity:7
當你讀取2個字節以後調用flip()方法 positon:0 limit:2 capacity:7
這裏就解決了我以前遇到的這三個屬性值變化的問題!!!
3、測試代碼
讀取完調用flip:
package com.cing.nio; import java.io.FileInputStream; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class NioTest1 { public static void main(String[] args) throws Exception{ FileInputStream fis = new FileInputStream("D:\\A.txt"); FileChannel fc = fis.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(7); output("初始化", buffer); fc.read(buffer); output("調用READ方法", buffer); buffer.flip(); output("第一次調用flip", buffer); while (buffer.remaining() > 0) { byte b = buffer.get(); } output("get()", buffer); buffer.flip(); output("第二次flip", buffer); fis.close(); } public static void output(String step, Buffer buffer) { System.out.println(step + " : "); System.out.println("buffer: " + buffer + ", "); } }
輸出結果爲:
初始化 : buffer: java.nio.HeapByteBuffer[pos=0 lim=7 cap=7], 調用READ方法 : buffer: java.nio.HeapByteBuffer[pos=3 lim=7 cap=7], 第一次調用flip : buffer: java.nio.HeapByteBuffer[pos=0 lim=3 cap=7], get() : buffer: java.nio.HeapByteBuffer[pos=3 lim=3 cap=7], 第二次flip : buffer: java.nio.HeapByteBuffer[pos=0 lim=3 cap=7],
讀取2字節以後調用flip:
package com.cing.nio; import java.io.FileInputStream; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class NioTest1 { public static void main(String[] args) throws Exception{ FileInputStream fis = new FileInputStream("D:\\A.txt"); FileChannel fc = fis.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(7); output("初始化", buffer); fc.read(buffer); output("調用READ方法", buffer); buffer.flip(); output("第一次調用flip", buffer); while (buffer.remaining() > 1) { byte b = buffer.get(); } output("get()", buffer); buffer.flip(); output("第二次flip", buffer); fis.close(); } public static void output(String step, Buffer buffer) { System.out.println(step + " : "); System.out.println("buffer: " + buffer + ", "); } }
輸出結果爲:
初始化 : buffer: java.nio.HeapByteBuffer[pos=0 lim=7 cap=7], 調用READ方法 : buffer: java.nio.HeapByteBuffer[pos=3 lim=7 cap=7], 第一次調用flip : buffer: java.nio.HeapByteBuffer[pos=0 lim=3 cap=7], get() : buffer: java.nio.HeapByteBuffer[pos=2 lim=3 cap=7], 第二次flip : buffer: java.nio.HeapByteBuffer[pos=0 lim=2 cap=7],