在开始对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代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 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代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// 获取一个容量为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());
|
注意此处用到了 Charset ,它的作用在上面已经说道,它主要用来进行编解码的,因此对字符串进行编码和解码时注意要使用相同的编码。
(3) IoBuffer的子类
为了更好的使用IoBuffer 进行开发, IoBuffer 提供了两个子类 BaseByteBuffer 和 ByteBufferProxy 。 BaseByteBuffer 实现了 IoBuffer 中定义的绝大多数方法。如果你在实际开发中要扩展适合于自己的方法时可以继承该类,因为它可以使你的实现更加简单。 ByteBufferProxy 中封装了一个 IoBuffer ,所有对 ByteBuffer 的操作都可以通过该类提供的方法来实现。
本文只是简单的介绍了IoBuffer 和 ByteBuffer 的基本知识,如果需要了解 IoBuffer 更多的信息请参考 Mina 的帮助文档和 Mina 的源码。