码迷,mamicode.com
首页 > 其他好文 > 详细

NIO的Buffer的相关操作

时间:2016-07-13 16:25:39      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

1、Buffer的创建
Buffer的创建可以通过两种方式。使用静态方法allocate()从堆中分配缓冲区,或者是一个既有的数组中创建缓冲区:

    //从堆中分配
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    //从既有的数组中创建
    byte array[] = new byte[1024];
    ByteBuffer buffer = ByteBuffer.wrap(array);

2、重置和清空缓冲区
Buffer 还提供了一些用于重置和清空Buffer状态的函数,如下:

public final Buffer rewind();
public final Buffer clear();
public final Buffer flip()
以上的三个函数有着类似的功能,它们重置了Buffer对象。这里所谓的重置,只是指重置了Buffer的各项标志位,并不真正清空Buffer的内容。3个函数的功能上也有所不同。
函数rewind将position置零,并清除标志位(mark)。它的作用在于为提取Buffer的有效数据做准备:
    out.write(buf) ;        //从Buffer读取数据写入channel
    buf.rewind();           //回滚Buffer
    buf.get(array);        //将Buffer的有效数据复制到数组中。

函数clear()也将Position置零,同时将Limit设置为capacity的大小,并清除了标志(mark)。由于清空了Limit,因此便无法得知Buffer内哪些数据是真实有效的。这个方法用于为重新写Buffer做准备:
    buf.clear();        //为读入数据到buffer做准备。
    in.read(buf);    //从通道读入数据

函数flip()先将limit设置到position所在位置,然后将Position置零,并清除标志位mark.它通常在读写转换时使用。

    buf.put(magic);    //将magic数组写入buffer
    in.read(buf);        //从通道读入给定信息,存放到Buffer中。
    buf.flip();    //将Buffer从写状态转为读状态
    out.write(buf);    //将magic和in通道中读入的信息,写到通道out中。

技术分享

3、读/写缓冲区
对Buffer进行读写操作是Buffer最为重要的操作。以ByteBuffer为例,JDK提供了以下常用读写操作:

public byte get();            //返回当前postion上的数据,并将positin位置向后移一位

public ByteBuffer get(byte[] dst)        //读取当前Buffer的数据到dst中,并恰当地移动position位置

public byte get(int index);        //读取给定index索引上的数据,不改变postion位置 。

public ByteBuffer put(byte b)            //当前位置写入给定的数据,postion位置向后移一位

public ByteBuffer put(int index,byte b)        //将数据b写入当前Buffer的index位置。

public final ByteBuffer put(byte[] src)        //将给定的数据写入当前Buffer.

4、标志缓冲区
标志(mark)缓冲区是一项在数据和凸显时很有用的功能,它就像书签一样,在数据处理的过程中,可以随时记录当前位置。然后在任意时刻,回到这个位置,从而加快或简化数据处理流程。
mark()用于记录当前位置,reset函数用于恢复到mark所在的位置。下面这段代码就充分了解释了这两个函数

import java.nio.ByteBuffer;

public class BufferTest {


    public static void main(String[] args) {

        //从堆中分配
        ByteBuffer b = ByteBuffer.allocate(15);
        //从既有的数组中创建
//        byte array[] = new byte[1024];
//        ByteBuffer buffer = ByteBuffer.wrap(array);
        for(int i = 0 ;i<10;i++){
            b.put((byte)i);
        }
        b.flip(); //准备读取数据
        for (int i = 0; i < b.limit(); i++) {
            System.out.print(b.get());
            if(i==4){
                b.mark();   //在第4个位置做mark
                System.out.print("( mark at "+i+"  )");
            }
        }
        b.reset();        //回到mark的位置,并处理后续数据
        System.out.println("\nreset to mark");
        while(b.hasRemaining()){        //后续所有数据都将处理
            System.out.print(b.get());
        }
    }
}

以下图是输出结果:
技术分享

5、复制缓冲区
public ByteBuffer duplicate()

这个函数对处理复杂的Buffer数据很有好处。因此新生在怕缓冲区和原缓冲共享相同的内存数据,并且,对任意一方的数据改动都是相互可见的,但是两者又独立维护了各自的postion,limit 和mark。这就大大增加了程序的灵活性。

6、缓冲区分片
缓冲区分片使用slice()方法实现,它将在现有的缓冲区中,创建新的子缓冲区,子缓冲区和父缓冲区共享数据。这个方法有助于将系统模块化。

  import java.nio.ByteBuffer;

public class BufferTest {


    public static void main(String[] args) {

        //从堆中分配
        ByteBuffer b = ByteBuffer.allocate(15);
        //从既有的数组中创建
//        byte array[] = new byte[1024];
//        ByteBuffer buffer = ByteBuffer.wrap(array);
        for(int i = 0 ;i<10;i++){
            b.put((byte)i);
        }
        b.position(2);    //当前位置为2
        b.limit(6);            //设置上限为6
        ByteBuffer subBuffer = b.slice(); //生成子缓冲区

        for (int i = 0; i < subBuffer.capacity(); i++) {
            byte bb = subBuffer.get(i);
            bb*=10;
            subBuffer.put(i,bb);
        }
        b.position(0);
        b.limit(b.capacity());
        while (b.hasRemaining()) {
            System.out.print(b.get()+",");
        }
    }
}

7、只读缓冲区
可以使用缓冲区对象的asReadOnlyBuffer()方法得到一个与当前缓冲区一致的,并且共享内存数据的只读缓冲区。只读缓冲区对于数据安全非常有用。当缓冲区作为参数传递给对象的某个方法时,由于无法确认该方法是否会破坏缓冲区数据,此时,使用只读缓冲区可以保证数据不被修改。同时,因为只读缓冲区和原始缓冲区是共享内存块的,因此,对原始缓冲区的修改,只读缓冲区也是可见的。

import java.nio.ByteBuffer;

public class BufferTest {


    public static void main(String[] args) {

        //从堆中分配
        ByteBuffer b = ByteBuffer.allocate(15);
        //从既有的数组中创建
//        byte array[] = new byte[1024];
//        ByteBuffer buffer = ByteBuffer.wrap(array);
        for(int i = 0 ;i<10;i++){
            b.put((byte)i);
        }
        ByteBuffer readOnly = b.asReadOnlyBuffer();  //创建只读缓冲区
        readOnly.flip();
        while (readOnly.hasRemaining()) {
            System.out.print(readOnly.get()+"  ");
        }
        System.out.println();
        b.put(2,(byte)20);    //修改了原始缓冲区的数据
        readOnly.flip();
        while (readOnly.hasRemaining()) {
            System.out.print(readOnly.get()+"  ");  //新的改动,在只读缓冲内可见
        }
    }
}

技术分享

NIO的Buffer的相关操作

标签:

原文地址:http://blog.csdn.net/angel_babys/article/details/51897700

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!