java - bytebuffer
<link rel="stylesheet" href="https://js.how234.com/third-party/SyntaxHighlighter/shCoreDefault.css" type="text/css" /><script type="text/javascript" src="https://js.how234.com/third-party/SyntaxHighlighter/shCore.js"></script><script type="text/javascript"> SyntaxHighlighter.all(); </script>
java bytebuffer是什麼,讓我們一起了解一下?
bytebuffer是buffer緩衝區的一種,看作提供了一些(未定義的)底層位元組儲存的檢視,需要注意的是幾個操作的影響:flip(),clear(),rewind(),還有就是在讀取或者寫入時,標誌的變化。
比如get()方法導致position加1,SocketChannel採用的是非阻塞非同步讀取流資料,在讀取的時候,通常是如下程式碼示例:
ByteBuffer.clear();SocketChannel.read(ByteBuffer);
如果流中有資料,就會把資料從position開始讀到ByteBuffer中,在讀取之前ByteBuffer的clear操作會把position置為0,limit置為capability,也就是相當於清空了之前的內容,但是ByteBuffer中陣列的內容在read之前是沒有改變的。
read之後,通常就是開始從ByteBuffer中提取讀到的資料,如果你的資料是以自己定義的資料包的格式進行傳送的,那你還需要判斷是否讀到了資料包的結尾,因為對流資料本身來說是沒有結尾這一說的。在提取資料之前,要先把position放到開始讀取時的位置,把limit放到當前位置,所以要flip一下,表示從position到limit的位置都是需要的資料。
這樣以來也存在一個問題,當一次讀到的ByteBuffer不包含完整的資料包或者包含多個數據包,那麼就需要在下一次繼續把這些包分拆出來。
另外一個可能會用到的操作就是ByteBuffer.rewind(),他會把position置為0,limit保持不變,可以用於重複讀取一段資料。
實戰操作:
ByteBuffer類提供了4個靜態工廠方法來獲得ByteBuffer的例項:
1、allocate(int capacity):從堆空間中分配一個容量大小為capacity的byte陣列作為緩衝區的byte資料儲存器。
2、allocateDirect(int capacity):是不使用JVM堆疊而是通過作業系統來建立記憶體塊用作緩衝區,它與當前作業系統能夠更好的耦合,因此能進一步提高I/O操作速度。但是分配直接緩衝區的系統開銷很大,因此只有在緩衝區較大並長期存在,或者需要經常重用時,才使用這種緩衝區。
3、wrap(byte[] array):這個緩衝區的資料會存放在byte陣列中,bytes陣列或buff緩衝區任何一方中資料的改動都會影響另一方。其實ByteBuffer底層本來就有一個bytes陣列負責來儲存buffer緩衝區中的資料,通過allocate方法系統會幫你構造一個byte陣列。
4、wrap(byte[] array,int offset, int length):在上一個方法的基礎上可以指定偏移量和長度,這個offset也就是包裝後byteBuffer的position,而length呢就是limit-position的大小,從而我們可以得到limit的位置為length+position(offset)。
測試方法:
public static void main(String args[]) throws FileNotFoundException { System.out.println("----------Test allocate--------"); System.out.println("before alocate:" + Runtime.getRuntime().freeMemory()); // 如果分配的記憶體過小,呼叫Runtime.getRuntime().freeMemory()大小不會變化? // 要超過多少記憶體大小JVM才能感覺到? ByteBuffer buffer = ByteBuffer.allocate(102400); System.out.println("buffer = " + buffer); System.out.println("after alocate:" + Runtime.getRuntime().freeMemory()); // 這部分直接用的系統記憶體,所以對JVM的記憶體沒有影響 ByteBuffer directBuffer = ByteBuffer.allocateDirect(102400); System.out.println("directBuffer = " + directBuffer); System.out.println("after direct alocate:" + Runtime.getRuntime().freeMemory()); System.out.println("----------Test wrap--------"); byte[] bytes = new byte[32]; buffer = ByteBuffer.wrap(bytes); System.out.println(buffer); buffer = ByteBuffer.wrap(bytes, 10, 10); System.out.println(buffer); }