深入理解Apache Mina (6)---- Java Nio ByteBuffer与Mina ByteBuffer的区别

来源:互联网 发布:尚学堂 大数据 百度云 编辑:程序博客网 时间:2024/05/19 20:20

为了对后续关于MinaProtocolFilter(编解码器)的编写有一个更好的理解,本文讲述一下关于Mina ByteBufferJava Nio ByteBuffer的区别。关于Java Nio ByteBufferMina ByteBuffer及其子类的类图在附件中都已经给出了。因为MinaByteBufferMina 2.0以上的版本中都改称IoBuffer。为了使后文关于ByteBuffer的名字不致混淆,Mina ByteBuffer都统称IoBufferJava Nio ByteBuffer统称ByteBuffer。关于IoBuffer中的对ByteBuffer扩展及一些重要的方法都在IoBuffer的类图中用红色方框标出。详细的信息请参考附件中。

 

 

在开始对IoBuffer的讨论前,先简单的讲述一下ByteBuffer的用法。IoBuffer是对ByteBuffer的一个封装。IoBuffer中的很多方法都是对ByteBuffer的直接继承。只是对ByteBuffer添加了一些扩展了更加实用的方法。

 

 

(1)ByteBuffer简介

ByteBuffer继承于Buffer类,ByteBuffer中存放的是字节,如果要将它们转换成字符串则需要使用CharsetCharset是字符编码。它提供了把字节流转换成字符串(解码)和将字符串转换成字节流(编码)的方法。这个和后面讲述的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. // JDK没有提供ByteBuffer的公开构造方法只能通过该  
  2.            // 方法来创建一个缓存区。       
  3.         ByteBuffer buffer = ByteBuffer.allocate(1024);  
  4.         // ========测试缓存读写一个字符串=======//  
  5.          String userName ="chinaestone";  
  6.          char[] charArray = userName.toCharArray();  
  7.            
  8.          System.out.println("这是往缓存中存放的 字符串");  
  9.          for(int i=0;i<charArray.length;i++){  
  10.              System.out.println(charArray[i]);  
  11.              buffer.putChar(charArray[i]);  
  12.          }  
  13.           
  14.          buffer.limit(buffer.position());  
  15.          buffer.position(0);  
  16.            
  17.          System.out.println();  
  18.          System.out.println("这是缓存中取出来的 字符串");  
  19.          while(buffer.hasRemaining()){  
  20.              System.out.println(buffer.getChar());  
  21.          }  
 

上面只是一个简单的演示程序,功能是实现对字符串的读写,比较,呵呵。关于如何向ByteBuffer读写字符串会在IoBuffer中详细讲解。

 

(2)IoBuffer简介

IoBuffer是对ByteBuffer的扩展,并不是和ByteBuffer毫无关系的。对Mina或者Socket应用来说,ByteBuffer提供的方法存在一下不足:

1)它没有提供足够可用的putset方法,例如:fillget/putString、 get/putAsciiInt()等。

2)很难将可变长度的数据放入ByteBuffer

基于以上的缺点,Mina提供了IoBuffer来补充了ByteBuffer的不足之处。

 

Let's drink code,来看看MinaIoBuffer是如何读写字符串的。

Java代码
  1. // 获取一个容量为1024字节的ByteBuffer  
  2.         ByteBuffer buffer = ByteBuffer.allocate(1024);        
  3.         // 设置系统字符集为utf-8  
  4.         Charset ch =Charset.forName("utf-8");  
  5.         // 获取utf-8的编码器  
  6.         CharsetEncoder encoder = ch.newEncoder();  
  7.         // 获取utf-8的解码器  
  8.         CharsetDecoder decoder = ch.newDecoder();  
  9.           
  10.         System.out.println(buffer.remaining());  
  11.         // 进行编码的字符串  
  12.         String cs = "中國壹石頭";  
  13.         // 将字符串编码后放入缓存    
  14.         buffer.putString(cs,encoder);         
  15.         System.out.println(buffer.remaining());       
  16.         // 将缓存的位置设为位置  
  17.         buffer.limit(buffer.position());  
  18.         // 将缓存的位置设为0  
  19.         buffer.position(0);  
  20.           
  21.         // 读取缓存中的字符串  
  22.         String str = buffer.getString(decoder);       
  23.         // 打印输出缓存中的信息  
  24.         System.out.println(str);  
  25.         System.out.println(buffer.remaining());  
 

注意此处用到了Charset,它的作用在上面已经说道,它主要用来进行编解码的,因此对字符串进行编码和解码时注意要使用相同的编码。

 

 

(3)IoBuffer的子类

为了更好的使用IoBuffer进行开发,IoBuffer提供了两个子类BaseByteBufferByteBufferProxyBaseByteBuffer实现了IoBuffer中定义的绝大多数方法。如果你在实际开发中要扩展适合于自己的方法时可以继承该类,因为它可以使你的实现更加简单。ByteBufferProxy中封装了一个IoBuffer,所有对ByteBuffer的操作都可以通过该类提供的方法来实现。 

 

本文只是简单的介绍了IoBufferByteBuffer的基本知识,如果需要了解IoBuffer更多的信息请参考Mina的帮助文档和Mina的源码。

原创粉丝点击