• ByteBuffer的mark、position、limit、flip、reset,get方法介绍ok


    ByteBuffer的mark、position、limit、flip、reset,get方法介绍

     
    http://blog.csdn.net/sunzhenhua0608/article/details/31778519
     

    首先说ByteBuffer中的get()方法,其API中说的不是很清楚(水平太菜,看着有点模糊),通过以下方法说明:

    [java] view plain copy
     
    1. byte[] buffer = new [in.remaining()];//其中in为IoBuffer实例,是<span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">ByteBuffer的子类</span>  
    2. in.duplicate().get(buffer);//这是in自己复制了一份并给buffer赋值。  
    [java] view plain copy
     
    1. in.get(buffer,0,10);<span style="font-family: Arial, Helvetica, sans-serif;">//</span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">该方法是从in(即IoBuffer)中取从0到10(不含第10个字节),共10个字节的值赋给buffer数组。</span>  

    java.nio.ByteBuffer的API中mark、position、limit、flip、reset几个方法非常重要,下面的例子结合源码可以帮助大家更好地掌握:

    Java代码  收藏代码
    1.      String str = "helloWorld";  
    2.         ByteBuffer buff  = ByteBuffer.wrap(str.getBytes());  
    3.         System.out.println("position:"+buff.position()+"  limit:"+buff.limit());  
    4.         //读取两个字节  
    5.         buff.get();  
    6.         buff.get();  
    7.         System.out.println("position:"+ buff.get(buff.position())+"  limit:"+buff.limit());  
    8.         buff.mark();  
    9.         System.out.println("position:"+buff.position()+"  limit:"+buff.limit());  
    10.         buff.flip();  
    11.         System.out.println("position:"+buff.position()+"  limit:"+buff.limit());<span style="white-space: pre;">    </span>  
    Java代码  收藏代码
    1. <pre class="java" name="code">输出结果:  
    2. position:0  limit:10  
    3. position:2  limit:10  
    4. position:2  limit:10  
    5. position:0  limit:2  
    6. </pre>  
    7.    
       我们以每位开发人员熟悉的”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代码  收藏代码
    1. System.out.println((char)buff.get()+""+(char)buff.get());  
        输出结果:he
        貌似这也没什么稀奇的,如果你在代码换成
     
    Java代码  收藏代码
    1. // System.out.println((char)buff.get()+""+(char)buff.get()  
    2.    System.out.println((char)buff.get()+""+(char)buff.get()+""+(char)buff.get());  
    Java代码  收藏代码
    1. 输出结果:<pre class="java" name="code">position:0    limit:10  
    2. Exception in thread "main" java.nio.BufferUnderflowException  
    3.     at java.nio.Buffer.nextGetIndex(Buffer.java:474)  
    4.     at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:117)  
    5.     at com.taobao.moxing.notify.Main.main(Main.java:33)position:2    limit:10  
    6. position:2   limit:10  
    7. position:0   limit:2  
    8. </pre>  
       为什么会抛异常呢?原因是limit的含义就像一个窗口,你当前能读到的数据就是当前窗口限制的(本例中即为2),如果这个窗口之外的所有元素都是不可读的。至此我想你和我就应该明白这几个参数的含义了吧。
        而至于reset方法,它是将当前的position设置为0,
         rewind是将mark重置为-1,position重置为0;
         clear方法是真正的重置,将mark=-1,position=0,limit=capacity(即当前buffer的容量)
     
    还有ByteBuffer中的get()方法,其API中说到
  • 相关阅读:
    php数组
    php运算符
    PHP数据类型
    面向对象3和继承
    面向对象2
    面向对象1
    语法整理php
    语法整理
    ajax
    数据库4
  • 原文地址:https://www.cnblogs.com/handsome1013/p/7680734.html
Copyright © 2020-2023  润新知