码迷,mamicode.com
首页 > 其他好文 > 详细

ByteBuffer 指標說明

时间:2015-01-10 13:46:25      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

當使用 java NIO 來讀寫檔案或 socket 時,一定會用到 ByteBuffer,大部份的人一開始會被它提供的許多 method 搞得很混亂,像是 flip、compact,甚至會質疑為什麼是提供這些 method ? 還有,ByteBuffer 中的三個指標 position、limit、capacity 會怎麼移動? 這裡做點簡單的說明。

  • allocate

  使用 ByteBuffer 前,一定要先為它向系統要一塊記憶體,如下:

ByteBuffer buffer = ByteBuffer.allocate(1024);

  這時候指標的位置會如下:

  技术分享

  position = 0

  limit = 1024

  capacity = 1024

  毫無疑問的,capacity 是指這個緩衝區的總量,這個數字在後續的各項操作都不會改變。

  position 是指,資料可以從這裡開始放進去,一直放到 limit 所指的位置。

  • read

  當我們用 socketChannel 讀取一段資料到緩衝區後會怎麼變化? 程式如下:

socketChannel.read(buffer);

  假設讀入的資料有 153 個 bytes,那麼,指標會如下變化:

  技术分享

  position = 153

  limit = 1024

  capacity = 1024

  position 指向下一個可將資料讀入緩衝區的位置,limit 仍是指可被讀入資料的限制,不可超過這個位置。

  通常,程式讀入一段資料後,當然會想要處理這段資料,處理前,會先下 flip 指令:

  技术分享

  limit 會被設定為原本 position 的值,即 153,position =0,這表示,之後的程式可透過 get() 來讀取 position 到 limit 這段區間的資料。

byte b = buffer.get();

  每呼叫一次 get(),即會傳回 position 所指位置的資料,並將 position 加1,position 最多可以加到 limit,如果 position 已經等於 limit,再呼叫 get(),會拋出 BufferUnderflowException 例外。

  有另外一個 method - get(i),可以指定要讀取特定位置的資料,這個 method 呼叫後除了傳回值外,不會移動 position。

  • wrap

  如果是要寫資料到 socket 呢? 這時候可能就會用到 wrap 這個 method,將一段原本放於 byte[] 陣列中的資料,放入 ByteBuffer 裡。

byte[] b = new byte[100];
// put something to b
ByteBuffer buffer = ByteBuffer.wrap(b);

  如下的程式,會產生一個長為 100 bytes 的 ByteBuffer,並放入 b 的資料,所以,各指標如下:

  position = 0

  limit = 100

  capacity = 100

  • write

  在 buffer 中有了資料後,要寫入 socket 連線裡,程式如下:

socketChannel.write(buffer);
if (buffer.hasRemaining()) {
        buffer.compact();
} else {
        buffer.clear();
}

  在第一行 write 之後,不一定就會全部 100 個 bytes 都寫進 socket 裡,有可能只寫了 90 個bytes,所以,程式會判斷是否還有剩下,有剩下就可能要再 write 一次,判斷有沒有剩下的方法是用 hasRemaining(),它其實是判斷 position 和 limit 間是否還有資料罷了。假設,只有寫出 90 bytes,指標會如何移動? 如下:

  position = 90

  limit = 100

  capacity = 100

  • compact

  承上,還有 10 bytes 未處理,假設我們希望再放入一些資料到 ByteBuffer 裡,那麼要怎麼做?

buffer.compact();

  沒錯,就是執行  compact(),這時未處的 10 bytes 資料會被移到最前面 index 0 ~ 9 的位置,指標會如下:

  position = 10

  limit = 100

  capacity = 100

  position 指向下一個可以放新資料的位置。

  • put

  上面介紹的 wrap 是一次放入一個 byte array 到 ByteBuffer 裡,另一個方法是 put,它可以一次只放一個 byte,也可以放一個 byte array,假設程式如下:

byte b = new byte(0x55);
buffer.put(b);

  因為僅放入一個 byte,position 會加 1,即變成 11,其餘不變。如果是要 put 一個 byte array ? 程式如下:

byte[] c = new byte[] { ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘ };
buffer.put(c);

  因為又放入了 7 個 bytes,因此 position = 18,其餘不變。

  • clear

  當在 ByteBuffer 裡的資料都處理完了,要將緩衝區裡的資料清楚,並將指標回復到原始狀態,就呼叫 clear()。

  • array

  雖然 NIO 的類別幾乎都是操作 ByteBuffer,但是,有時還是會有需要將 ByteBuffer 的內容轉為 byte[],這時可以呼叫 array(),要特別注意的是,array() 並非只傳回 position 和 limit 間的內容,而是傳回 0 ~ capacity 間的內容。

 

ByteBuffer 指標說明

标签:

原文地址:http://www.cnblogs.com/stevwn/p/4214720.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!