為了對後續關於Mina 的 ProtocolFilter(
轉碼器 ) 的編寫有一個更好的理解,本文講述一下關於 Mina ByteBuffer
和 Java Nio ByteBuffer 的區別。關於 Java Nio ByteBuffer
和 Mina ByteBuffer 及其子類的類圖在附件中都已經給出了。因為
Mina 的 ByteBuffer 在 Mina 2.0
以上的版本中都改稱 IoBuffer 。為了使後文關於 ByteBuffer
的名字不致混淆, Mina ByteBuffer 都統稱 IoBuffer
, Java Nio ByteBuffer 統稱 ByteBuffer
。關於 IoBuffer 中的對 ByteBuffer
擴充及一些重要的方法都在 IoBuffer 的類圖中用紅色方框標出。詳細的資訊請參考附件中。
在開始對IoBuffer 的討論前,先簡單的講述一下 ByteBuffer
的用法。 IoBuffer 是對 ByteBuffer
的一個封裝。 IoBuffer 中的很多方法都是對 ByteBuffer
的直接繼承。只是對 ByteBuffer 添加了一些擴充了更加實用的方法。
(1) ByteBuffer簡介
ByteBuffer繼承於 Buffer 類,
ByteBuffer 中存放的是位元組,如果要將它們轉換成字串則需要使用 Charset
, Charset 是字元編碼。它提供了把位元組流轉換成字串 (
解碼 ) 和將字串轉換成位元組流 ( 編碼
) 的方法。這個和後面講述的 Mina 的編解碼的工作原理類似。對
ByteBuffer 的訪問可以使用 read() ,
write() 等方法。
ByteBuffer有一下三個重要的屬性:
1) 容量(capacity) :表示該緩衝區可以存放多少資料。
2) 極限(limit) :表示讀寫緩衝的位置,不能對超過位置進行資料的讀或寫操作。
位置(position) :表示下一個緩衝區的讀寫單元。每讀寫一次緩衝區,位置都會變化。位置是一個非負整數。
ByteBuffer的這三個屬性相當於三個標記位,來表示程式可以讀寫的地區:
簡單的表示了容量、極限、位置在緩衝區中的位置。其中極限只能標記容量以內的位置,即極限值的大小不能超過容量。同樣位置是用來標記程式對緩衝區進行讀或寫操作的開始位置。程式只能在極限以內的範圍進行讀寫,即讀寫操作不能超過極限的範圍,所以位置值的大小也不能超過極限。三者的大小關係為:容量>
極限 > 位置 >=0 。
上面說到ByteBuffer 的三個屬性只是緩衝區的標記位置。那麼如何改變這些標記的位置呢?
ByteBuffer 提供了一下三種方法來改變上面的屬性值。
1) clear():極限設定為容量,位置設為 0
。
2) flip():極限設為位置,位置設為 0
。
3)rewind():不改變極限,位置設為 0 。
Java代碼
- // JDK沒有提供ByteBuffer的公開構造方法只能通過該
- // 方法來建立一個緩衝區。
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- // ========測試緩衝讀寫一個字串=======//
- String userName ="chinaestone";
- char[] charArray = userName.toCharArray();
-
- System.out.println("這是往緩衝中存放的 字串");
- for(int i=0;i<charArray.length;i++){
- System.out.println(charArray[i]);
- buffer.putChar(charArray[i]);
- }
-
- buffer.limit(buffer.position());
- buffer.position(0);
-
- System.out.println();
- System.out.println("這是緩衝中取出來的 字串");
- while(buffer.hasRemaining()){
- System.out.println(buffer.getChar());
- }
[java]
view plaincopyprint?
- // JDK沒有提供ByteBuffer的公開構造方法只能通過該
- // 方法來建立一個緩衝區。
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- // ========測試緩衝讀寫一個字串=======//
- String userName ="chinaestone";
- char[] charArray = userName.toCharArray();
-
- System.out.println("這是往緩衝中存放的 字串");
- for(int i=0;i<charArray.length;i++){
- System.out.println(charArray[i]);
- buffer.putChar(charArray[i]);
- }
-
- buffer.limit(buffer.position());
- buffer.position(0);
-
- System.out.println();
- System.out.println("這是緩衝中取出來的 字串");
- while(buffer.hasRemaining()){
- System.out.println(buffer.getChar());
- }
// JDK沒有提供ByteBuffer的公開構造方法只能通過該 // 方法來建立一個緩衝區。 ByteBuffer buffer = ByteBuffer.allocate(1024);// ========測試緩衝讀寫一個字串=======// String userName ="chinaestone"; char[] charArray = userName.toCharArray(); System.out.println("這是往緩衝中存放的 字串"); for(int i=0;i<charArray.length;i++){ System.out.println(charArray[i]); buffer.putChar(charArray[i]); } buffer.limit(buffer.position()); buffer.position(0); System.out.println(); System.out.println("這是緩衝中取出來的 字串"); while(buffer.hasRemaining()){ System.out.println(buffer.getChar()); }
上面只是一個簡單的示範程式,功能是實現對字串的讀寫,比較“ 笨
” ,呵呵。關於如何向 ByteBuffer 讀寫字串會在
IoBuffer 中詳細講解。
(2) IoBuffer簡介
IoBuffer是對 ByteBuffer 的擴充,並不是和
ByteBuffer 毫無關係的。對 Mina 或者
Socket 應用來說, ByteBuffer 提供的方法存在一下不足:
1) 它沒有提供足夠可用的put 和
set 方法,例如: fill 、 get/putString
、 get/putAsciiInt() 等。
2)很難將可變長度的資料放入 ByteBuffer 。
基於以上的缺點,Mina 提供了 IoBuffer
來補充了 ByteBuffer 的不足之處。
Let's drink code,來看看 Mina 的
IoBuffer 是如何讀寫字串的。
Java代碼
- // 擷取一個容量為1024位元組的ByteBuffer
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- // 設定系統字元集為utf-8
- Charset ch =Charset.forName("utf-8");
- // 擷取utf-8的編碼器
- CharsetEncoder encoder = ch.newEncoder();
- // 擷取utf-8的解碼器
- CharsetDecoder decoder = ch.newDecoder();
-
- System.out.println(buffer.remaining());
- // 進行編碼的字串
- String cs = "中國壹石頭";
- // 將字串編碼後放入緩衝
- buffer.putString(cs,encoder);
- System.out.println(buffer.remaining());
- // 將緩衝的位置設為位置
- buffer.limit(buffer.position());
- // 將緩衝的位置設為0
- buffer.position(0);
-
- // 讀取緩衝中的字串
- String str = buffer.getString(decoder);
- // 列印輸出緩衝中的資訊
- System.out.println(str);
- System.out.println(buffer.remaining());
[java]
view plaincopyprint?
- // 擷取一個容量為1024位元組的ByteBuffer
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- // 設定系統字元集為utf-8
- Charset ch =Charset.forName("utf-8");
- // 擷取utf-8的編碼器
- CharsetEncoder encoder = ch.newEncoder();
- // 擷取utf-8的解碼器
- CharsetDecoder decoder = ch.newDecoder();
-
- System.out.println(buffer.remaining());
- // 進行編碼的字串
- String cs = "中國壹石頭";
- // 將字串編碼後放入緩衝
- buffer.putString(cs,encoder);
- System.out.println(buffer.remaining());
- // 將緩衝的位置設為位置
- buffer.limit(buffer.position());
- // 將緩衝的位置設為0
- buffer.position(0);
-
- // 讀取緩衝中的字串
- String str = buffer.getString(decoder);
- // 列印輸出緩衝中的資訊
- System.out.println(str);
- System.out.println(buffer.remaining());
// 擷取一個容量為1024位元組的ByteBufferByteBuffer buffer = ByteBuffer.allocate(1024);// 設定系統字元集為utf-8Charset ch =Charset.forName("utf-8");// 擷取utf-8的編碼器CharsetEncoder encoder = ch.newEncoder();// 擷取utf-8的解碼器CharsetDecoder decoder = ch.newDecoder();System.out.println(buffer.remaining());// 進行編碼的字串String cs = "中國壹石頭";// 將字串編碼後放入緩衝buffer.putString(cs,encoder);System.out.println(buffer.remaining());// 將緩衝的位置設為位置buffer.limit(buffer.position());// 將緩衝的位置設為0buffer.position(0);// 讀取緩衝中的字串String str = buffer.getString(decoder);// 列印輸出緩衝中的資訊System.out.println(str);System.out.println(buffer.remaining());
注意此處用到了 Charset ,它的作用在上面已經說道,它主要用來進行編解碼的,因此對字串進行編碼和解碼時注意要使用相同的編碼。
(3) IoBuffer的子類
為了更好的使用IoBuffer 進行開發, IoBuffer
提供了兩個子類 BaseByteBuffer 和 ByteBufferProxy
。 BaseByteBuffer 實現了 IoBuffer
中定義的絕大多數方法。如果你在實際開發中要擴充適合於自己的方法時可以繼承該類,因為它可以使你的實現更加簡單。 ByteBufferProxy
中封裝了一個 IoBuffer ,所有對 ByteBuffer
的操作都可以通過該類提供的方法來實現。
本文只是簡單的介紹了IoBuffer 和 ByteBuffer
的基本知識,如果需要瞭解 IoBuffer 更多的資訊請參考 Mina
的協助文檔和 Mina 的源碼。