Android的NIO之ByteBuffer解析与实例代码

谈及Java NIO,最核心的三个组件就是:

  • Channel 通道
  • ByteBuffer 读写缓冲区
  • Selector 多路复用器

ByteBuffer的读写操作

ByteBuffer为NIO中的字节缓冲区,相对于BIO的Stream流只支持写入或者读取单向操作,ByteBuffer是双向的,支持读和写。

属性与方法

DirectByteBuffer

使用的是操作系统级别的内存,分配比较慢,但是数据的读写比较快,因为少了一次从系统内存到JVM内存的复制过程。

初始化方法:
ByteBuffer.allocateDirect(1024 * 4);

HeapByteBuffer

使用的是JVM的堆内存,对于JVM来说,分配比较快,但是读写比较慢,因为需要将操作系统内存里的数据复制到JVM内存。

初始化方法:
ByteBuffer.allocate(1024 * 4);

capacity

ByteBuffer的容量,这个值在ByteBuffer初始化的时候就确定下来了。不论是在读还是在写模式下,这个值都不变。

position

写模式下:该值表示当前写到了ByteBuffer的哪个位置,ByteBuffer初始化时,这个值为0;position的最大值为capacity-1。
读模式下:当从写模式切换到读模式,会将position重置为0,即从ByteBuffer的起始位置开始读取数据。

limit

写模式下:limit为最大可写入的数据量,即ByteBuffer的最大容量,值为capacity;
读模式下:当从写模式切换从读模式,limit将会被设置为读模式下的position值,即可读取的最大数据量。

flip()

将写模式切换为读模式,会触发的对核心属性的操作:
将position设置为0,即从ByteBuffer起始位置开始读。
将limit设置为写模式下position的值,即最大可读取的数据量大小。

mark()

标记当前position位置

reset()

将position指向上一次mark()所指向的位置,可以从这个位置重复向下读取数据

clear()

在逻辑上清空ByteBuffer里的数据,实际上不清空数据;
会触发的动作:将limit设置为capacity,position指向起始位置0,提示:如果ByteBuffer中的数据并未完全读完,调用这个方法将忽略那些未读取的数据。

compact()

如果并未读取完ByteBuffer中的数据,调用compact()会将position~limit之间的数据拷贝到ByteBuffer的起始处,并且position为剩余数据量的大小,下次再往ByteBuffer中写入数据时,将在position位置继续往下写,不会覆盖历史数据。

hasRemaining()

判断缓冲区中是否还有未读数据

put()

将数据写入ByteBuffer的方式, byteBuffer.put(x)

get()

从ByteBuffer中读取数据的方式,byteBuffer.get()

实例代码:

/**
 * ByteBuffer的代码演示
 *
 * @author futao
 * @date 2020/7/7
 */
public class ByteBufferDemo {
    
    
    public static void main(String[] args) {
    
    
        // ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 4);
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 4);

        // Q: 初始化之后,这三个值分别是多少呢?
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        //向ByteBuffer写入数据
        byteBuffer.put("hello, 喜欢天文的pony站长~".getBytes(Constants.CHARSET));

        // Q: 向ByteBuffer中写入数据之后,哪些值会发生变化呢?
        System.out.println(StringUtils.repeat("=", 10) + "写入数据之后" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        //将ByteBuffer从写模式调整为读模式
        byteBuffer.flip();

        //将ByteBuffer从写模式调整为读模式之后,ByteBuffer的哪些值会发生变化?
        System.out.println(StringUtils.repeat("=", 10) + "调整ByteBuffer为读模式之后" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        //从ByteBuffer中读取一个字节
        byteBuffer.get();
        // Q: 从ByteBuffer中读取一个字节之后,哪些值会发生变化?
        System.out.println(StringUtils.repeat("=", 10) + "从ByteBuffer中读取一个字节之后" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        // 记录一个标记
        byteBuffer.mark();
        // 继续往下读取
        byteBuffer.get();
        System.out.println(StringUtils.repeat("=", 10) + "记录一个标记之后继续往下读取" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        //重置position到上一次mark()的标记位置
        byteBuffer.reset();
        System.out.println(StringUtils.repeat("=", 10) + "reset之后" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        System.out.println("byteBuffer中是否还有数据:" + byteBuffer.hasRemaining());
        //拷贝未读取的数据到缓冲区最前面
        byteBuffer.compact();
        System.out.println(StringUtils.repeat("=", 10) + "compact之后" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());

        //逻辑上清空数据=>实际上只是指针的变化
        byteBuffer.clear();
        System.out.println(StringUtils.repeat("=", 10) + "clear之后" + StringUtils.repeat("=", 10));
        System.out.println("position: " + byteBuffer.position());
        System.out.println("capacity: " + byteBuffer.capacity());
        System.out.println("limit: " + byteBuffer.limit());
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_38387929/article/details/120887477