• 【MINA】缓存区ByteBuffer和IOBuffer你要了解的常用知识


    mina中IOBuffer是Nio中ByteBuffer的衍生类,主要是解决Bytebuffer的两个不足

    1、没有提供足够灵活的get/putXXX方法

    2、它容量固定,难以写入可变长度的数据

    特点:

    1、通过allocate分配空间,

    2、包装现有的NIOBu和array,

    3、自拓展,

    4自压缩,

    5、衍生缓冲区,

    6、可改变缓冲区的分配策略

    1.先来学习下ByteBuffer你要了解的东西
    摘自 http://blackbeans.iteye.com/blog/836103
    这是一篇好文章,对ByteBuff讲的很清楚

    查看ByteBuffer的API,看的我是一头雾水,搞不清什么mark、position、limit、flip、reset几个的用法,先看下面的例子:
    Java代码 收藏代码

    String str = "helloWorld";
    ByteBuffer buff = ByteBuffer.wrap(str.getBytes());
    System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
    //读取两个字节
    buff.get();
    buff.get();
    System.out.println("position:"+ buff.get(buff.position())+"\t limit:"+buff.limit());
    buff.mark();
    System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
    buff.flip();
    System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());<span style="white-space: pre;"> </span>

    Java代码 收藏代码

    <pre name="code" class="java">输出结果:
    position:0 limit:10
    position:2 limit:10
    position:2 limit:10
    position:0 limit:2
    </pre>

    我们以每位开发人员熟悉的”helloworld“,用ByteBuffer将字符串包装,由于ByteBuffer是一个抽象类,通过wrap包装的对象将实际返回的是一个HeapByteBuffer对象。由此可知HeapByteBuffer是ByteBuffer的子类,同样的ByteBuffer又是Buffer抽象类的子类。以上提到的mark、position、limit、flip、reset都是出自于Buffer这个抽象类。
    下面我们来解析几个方法的,当我们调用了wrap方法后Buffer中初始化的结构是:
    注释:
    m:mark;
    p:position;
    L:limit;

    初始情况下mark是指向第一个元素之前的的即-1,postion为指向第一个元素为0.而Limit是被赋值为byte[]的长度。
    因此这就是打印结果的第一行。
    m p L
    -1 0 1 2 3 4 5 6 7 8 9
    H E L L O W O R L D
    当我们连续调用两次get()方法获得两个个字节,每次调用都会触发position++操作,那么此时position就会移动到index = 2的的地方,而这个时候Limit和mark是不会发生变化的。如果将读取的两个字节打印会是H和E,因此执行结果第二行会有position:2 limit:10结果.
    m、p L
    -1 0 1 2 3 4 5 6 7 8 9
    H E L L O W O R L D
    读取完毕后我们使用mark,这个时候mark会从-1移动到2和position指向同一个元素,可以看见Limit是不会发生改变的。
    m p L
    -1 0 1 2 3 4 5 6 7 8 9
    H E L L O W O R L D
    使用了mark标记的当前的position后,如果们调用flip,这个时候Limit就会指向position的位置,并将mark和position还原为初始值。这样就知道了limit当前的就为2,什么意思呢?就是说当前可以读的字节数是2。
    我们可以尝试一下如下代码:

    Java代码 收藏代码

    System.out.println((char)buff.get()+""+(char)buff.get());

    输出结果:he
    貌似这也没什么稀奇的,如果你在代码换成

    Java代码 收藏代码

    // System.out.println((char)buff.get()+""+(char)buff.get()
    System.out.println((char)buff.get()+""+(char)buff.get()+""+(char)buff.get());

    Java代码 收藏代码

    输出结果:<pre name="code" class="java">position:0 limit:10
    Exception in thread "main" java.nio.BufferUnderflowException
    at java.nio.Buffer.nextGetIndex(Buffer.java:474)
    at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:117)
    at com.taobao.moxing.notify.Main.main(Main.java:33)position:2 limit:10
    position:2 limit:10
    position:0 limit:2
    </pre>

    为什么会抛异常呢?原因是limit的含义就想一个窗口,你当前能读到的数据就是当前窗口限制的(本例中即为2),如果这个窗口之外的所有元素都是不可读的。至此我想你和我就应该明白这几个参数的含义了吧。
    而至于reset方法,它是将当前的position设置为0,
    rewind是将mark重置为-1,position重置为0;
    clear方法是真正的重置,将mark=-1,position=0,limit=capacity(即当前buffer的容量)

    2.看看IOBuffer我们需要了解的东西,摘自http://www.360doc.com/content/12/0410/15/9184201_202487090.shtml Apache Mina Server 2.0 中文参考手册


    (7.)IoBuffer:

    这个接口是对JAVA NIO 的ByteBuffer 的封装,这主要是因为ByteBuffer 只提供了对基本

    数据类型的读写操作,没有提供对字符串等对象类型的读写方法,使用起来更为方便,另外,

    ByteBuffer 是定长的,如果想要可变,将很麻烦。IoBuffer 的可变长度的实现类似于

    StringBuffer。IoBuffer 与ByteBuffer 一样,都是非线程安全的。本节的一些内容如果不

    清楚,可以参考java.nio.ByteBuffer 接口。

    这个接口有如下常用的方法:

    A. static IoBuffer allocate(int capacity,boolean useDirectBuffer):

    这个方法内部通过SimpleBufferAllocator 创建一个实例,第一个参数指定初始化容量,第

    二个参数指定使用直接缓冲区还是JAVA 内存堆的缓存区,默认为false。

    B. void free():

    释放缓冲区,以便被一些IoBufferAllocator 的实现重用,一般没有必要调用这个方法,除

    非你想提升性能(但可能未必效果明显)。

    C. IoBuffer setAutoExpand(boolean autoExpand):

    这个方法设置IoBuffer 为自动扩展容量,也就是前面所说的长度可变,那么可以看出长度

    可变这个特性默认是不开启的。

    D. IoBuffer setAutoShrink(boolean autoShrink):

    这个方法设置IoBuffer 为自动收缩,这样在compact()方法调用之后,可以裁减掉一些没

    有使用的空间。如果这个方法没有被调用或者设置为false,你也可以通过调用shrink()

    方法手动收缩空间。

    E. IoBuffer order(ByteOrder bo):

    这个方法设置是Big Endian 还是Little Endian,JAVA 中默认是Big Endian,C++和其他

    语言一般是Little Endian。

    F. IoBuffer asReadOnlyBuffer():

    这个方法设置IoBuffer 为只读的。

    G. Boolean prefixedDataAvailable(int prefixLength,int maxDataLength):

    这个方法用于数据的最开始的1、2、4 个字节表示的是数据的长度的情况,prefixLentgh

    表示这段数据的前几个字节(只能是1、2、4 的其中一个)的代表的是这段数据的长度,

    maxDataLength 表示最多要读取的字节数。返回结果依赖于等式

    remaining()-prefixLength>=maxDataLength,也就是总的数据-表示长度的字节,剩下的字

    节数要比打算读取的字节数大或者相等。

    H. String getPrefixedString(int prefixLength,CharsetDecoder decoder):

    如果上面的方法返回true,那么这个方法将开始读取表示长度的字节之后的数据,注意要

    保持这两个方法的prefixLength 的值是一样的。

    G、H 两个方法在后面讲到的PrefixedStringDecoder 中的内部实现使用。

    IoBuffer 剩余的方法与ByteBuffer 都是差不多的,额外增加了一些便利的操作方法,例如:

    IoBuffer putString(String value,CharsetEncoder encoder)可以方便的以指定的编码方

    式存储字符串、InputStream asInputStream()方法从IoBuffer 剩余的未读的数据中转为

    输入流等。

  • 相关阅读:
    Activity.startManagingCursor方法
    android SQLite使用SQLiteOpenHelper类对数据库进行操作
    Android类参考---SQLiteOpenHelper
    使用SQLiteOpenHelper类对数据库简单操作
    dom4j 最常用最简单的用法(转)
    setContentView()与LayoutInflater.inflate()作用
    Android listview与adapter用法
    ListView属性及divider设置分割线
    android布局属性详解
    Android layout属性之gravity和layout_gravity
  • 原文地址:https://www.cnblogs.com/dagangzi/p/4714756.html
Copyright © 2020-2023  润新知