Java NIO 之缓冲区

来源:互联网 发布:java并发编程 编辑:程序博客网 时间:2024/05/19 13:55

基础

  1.  概念上,缓冲区是包在一个对象内的基本数据元素数组,所有的缓冲区都具有四个属性来提供关于其所包含的数据元素的信息。    1)容量:缓冲区所能容纳的数据元素的最大数量。在创建时被设定,并且永远不能改变。    2)上界:缓冲区内第一个不能被读或写的元素。    3)位置:下一个要被读或写的元素的索引。    4)标记:一个备忘位置。

2.填充数据

buffer.put((byte)'H').put((byte)'e'); // 这里的buffer是一个ByteBuffer对象,所以字符都要进行强转

这样我们就可以往缓冲区内填充数据,在不超出容量的情况下都是正确的。

3.反转
在缓冲区写满后,需要将其清空,但现在的position位置指的是最后插入数据的下一个位置,所以需要将position重新设置为0,此时就需要上界来指定我们插入数据的末端。利用以下代码实现

buffer.flip();     //等同于buffer.limit(buffer.position()).poeition(0);
public class Demo01 {    private static int index = 0;    private static String [] strings = {            "A random string value",            "The product of an infinite number of monkeys",            "Hey hey we're the Monkees",            "Opening act for the Monkees: Jimi Hendrix",            "'Scuse me while I kiss this fly",            "Help Me! Help Me!",    };    public static void main(String[] args) {        // TODO Auto-generated method stub        CharBuffer buffer = CharBuffer.allocate(100); //初始化缓冲区        while (fillBuffer (buffer)){            buffer.flip();  //反转缓冲区            drainBuffer(buffer);              buffer.clear();  //清除缓冲区        }    }    private static boolean fillBuffer(CharBuffer buffer) {        if(index >= strings.length){            return false;        }        String string = strings[index++];        for (int i = 0; i <string.length(); i++) {            buffer.put(string.charAt(i));   //注意每次取出数据的时候都会使position增加一位        }        return true;    }    private static void drainBuffer(CharBuffer buffer) {        // TODO Auto-generated method stub        while(buffer.hasRemaining()){            System.out.println(buffer.get());        }        System.out.println("");    }}

3.标记:用于缓冲区记住一个位置并在之后将其返回
在mark()函数调用之前是未定义的,调用时标记被设为当前位置的值。reset()函数将位置设为当前的标记值。

buffer.position(2).mark().position(4); //此时如果上界在6处,则会发送两个字节,调用reset()后会发送4字节

4.比较
所有的缓冲区都提供了一个常规的equals()函数用于测试是否相等和一个compareTo()函数用于比较缓冲区。下面的代码用来测试两个缓冲区是否相等。

if(buffer1.euqals(buffer2)){        doSomething();  }

5**批量移动**

char [] Array = new char[1024]; int len = buffer.remaining(); //确定缓冲区内的数据数量,如果数量小于要指定拷贝的数组的容量会抛出异常buffer.get(Array,0,len);  //拷贝数据到数组中,这里的len不能超过缓冲区的数据数量doSomeing(Array,len);

创建缓冲区

新的缓冲区是由分配或包装操作创建的。分配操作创建一个缓冲区对象并分配一个私有的空间来储存容量大小的数据元素。包装操作创建一个缓冲区对象但是不分配任何空间来储存数据元素。它使用提供的数组作为存储空间来储存缓冲区中的数据元素。

CharBuffer buffer = CharBuffer.allocate(100); //从堆空间分配一个char型数组作为存储器来储存100个char变量
char[] array = new char[100];CharBuffer buffer = CharBuffer.wrap(array); //缓冲区用的是数组的空间,对缓冲区的改变会造成数组的变化

这两种方法会创建的缓冲区都是间接的,使用的是备份数组。如果想要获取他们,可以使用hasArray()判断是否存在可存取的数组,如果有,调用array()返回这个数组存储空间的引用。

复制缓冲区

Duplicate()函数可以创建一个与原始缓冲区相似的新缓冲区。两个缓冲区共享数据元39
素,拥有同样的容量,但每个缓冲区拥有各自的位置,上界和标记属性。对一个缓冲区内的数
据元素所做的改变会反映在另外一个缓冲区上。

CharBuffer buffer = CharBuffer.allocate(8);CharBuffer dupeBuffer = buffer.duplicate(); 

分割缓冲区与复制相似,但 slice()创建一个从原始缓冲区的当前位置开始的新缓冲区,并且其容量是原始缓冲区的剩余元素数量( limit-position)。这个新缓冲区与原始缓冲区共享一段数据元素子序列。分割出来的缓冲区也会继承只读和直接属性。

假如要创建一个映射到数组位置 12-20( 9 个元素)的 buffer 对象,应使用下面的代码实现:

char [] myBuffer = new char [100];CharBuffer cb = CharBuffer.wrap (myBuffer);cb.position(12).limit(21);CharBuffer sliced = cb.slice( );
0 0
原创粉丝点击