ByteBuffer常用方法与分析

目录

目标

常用API

工具方法

演示案例

allocate(int capacity)和allocateDirect(int capacity)

put()和get()

flip()和hasRemaining()

clear()

compact()

 wrap()

总结


目标

掌握ByteBuffer常用方法,分析ByteBuffer对象在切换读写模式的情况下基本属性的变化情况。

常用API

方法 描述 案例
allocate(int capacity) 分配capacity个字节的缓冲区。返回HeapByteBuffer对象,即jdk内存堆字节缓冲区。 ByteBuffer buffer = ByteBuffer.allocate(8);
allocateDirect(int capacity) 分配capacity个字节的缓冲区。返回DirectByteBuffer对象,即直接内存字节缓冲区。 ByteBuffer buffer = ByteBuffer.allocateDirect(8);
compact() 将ByteBuffer切换到写入模式,从position处将缓冲区的字节移动到起始位置。 buffer.compact();
get() 从ByteBuffer中读取1个字节,并将position向后移动1位。 buffer.get();
get(int index) 根据index获取指定位置的字节,不会移动position。 buffer.get(1);
put(byte[] src) 向ByteBuffer写字节数组数据。 buffer.put(new byte[]{'1','a'});
buffer.put("1a".getBytes());
put(byte b) 向ByteBuffer写字节数据。 buffer.put((byte)127);
wrap(byte[] array) 向ByteBuffer写字节数组数据。对缓冲区的修改将导致数组被修改,反之亦然。
新缓冲区的大小和limit为字节数组的长度。
ByteBuffer.wrap("Hello World.".getBytes());
flip() 将ByteBuffer切换到读模式,position设置为0,limit设置为ByteBuffer内最后1个字节所在的索引数。 buffer.flip();
clear() 将position设置为0,limit设置为capacity,mark被丢弃。 buffer.clear();
capacity() 获取ByteBuffer的容量大小。 buffer.capacity();
hasRemaining() position和limit之间是否有任何元素。 buffer.hasRemaining();

工具方法

    public void bufferDetails(ByteBuffer buffer) {
        System.out.print("position="+buffer.position());
        System.out.print(";limit="+buffer.limit());
        System.out.println(";capacity="+buffer.capacity());
        //读取数据不移动索引。
        for (int i = 0; i < buffer.limit(); i++) {
            System.out.print(buffer.get(i));
            System.out.print(" ");
        }
        System.out.println("\n");
    }

演示案例

allocate(int capacity)和allocateDirect(int capacity)

    /**
     * JVM堆内存字节缓冲区
     * 直接内存字节缓冲区
     */
    public void allocateTest(){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        //是否是直接直接内存字节缓冲区
        System.out.println(buffer.isDirect());

        ByteBuffer buffer2 = ByteBuffer.allocateDirect(8);
        //是否是直接直接内存字节缓冲区
        System.out.println(buffer2.isDirect());

    }

put()和get()

    /**
     * 从ByteBuffer中读取1个字节,并将position向后移动1位。
     */
    public void getAndPutTest(){
        ByteBuffer buffer = ByteBuffer.allocateDirect(20);
        //注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
        buffer.put("Hello World !".getBytes());
        //切换到读模式
        buffer.flip();
        //position=0
        System.out.println(buffer.position());
        //输出72,ASCII表中H就是72
        System.out.println(buffer.get());
        //position=1
        System.out.println(buffer.position());
        //继续读取字节缓冲区返回position=1位置的数据,即返回e。
        System.out.println((char)buffer.get());
    }

flip()和hasRemaining()

    /**
     * flip():将ByteBuffer切换到读模式,position设置为0,limit设置为ByteBuffer内最后1个字节所在的索引数。
     * hasRemaining()	position和limit之间是否有任何元素。
     */
    public void flipTest() {
        ByteBuffer buffer = ByteBuffer.allocateDirect(16);
        //注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
        buffer.put("123456789".getBytes());
        bufferDetails(buffer);
        //切换到读模式
        buffer.flip();
        bufferDetails(buffer);
        //读取数据并移动position。
        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
        //position=9。
        bufferDetails(buffer);
    }

打印结果

ByteBuffer常用方法与分析_第1张图片

clear()

    /**
     * clear():将position设置为0,limit设置为capacity,mark被丢弃。
     */
    public void clearTest() {
        ByteBuffer buffer = ByteBuffer.allocateDirect(16);
        //注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
        buffer.put("123456789".getBytes());
        //切换到读模式
        buffer.flip();
        //读取数据并移动position。
        while(buffer.hasRemaining()){
            buffer.get();
        }
        //position=9。
        bufferDetails(buffer);
        //position=0;limit=16;capacity=16
        buffer.clear();
        bufferDetails(buffer);
    }

打印结果 

ByteBuffer常用方法与分析_第2张图片

compact()

    /**
     * compact():将ByteBuffer切换到写入模式,从position处将缓冲区的字节移动到起始位置。
     */
    public void compactTest(){
        ByteBuffer buffer = ByteBuffer.allocateDirect(16);
        //注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
        buffer.put("123456789".getBytes());
        //切换到读模式
        buffer.flip();
        //读取1个字节。此时的buffer为:position=1;limit=9;capacity=16
        buffer.get();
        buffer.compact();
        bufferDetails(buffer);
        //切换到读模式
        buffer.flip();
        //position=0;limit=8;capacity=16,由此打印证明最后一个9不会被重复读取。
        bufferDetails(buffer);
    }

打印结果

 ByteBuffer常用方法与分析_第3张图片

 wrap()

    /**
     * 向ByteBuffer写字节数组数据。对缓冲区的修改将导致数组被修改,反之亦然。
     * 新缓冲区的大小和limit为字节数组的长度。
     */
    public void wrapTest(){
        byte[] bytes = "123456789".getBytes();
        ByteBuffer buffer =  ByteBuffer.wrap(bytes);
        bufferDetails(buffer);
        buffer.get();
        buffer.compact();
        bufferDetails(buffer);
        //打印234567899,证明了我们对ByteBuffer操作影响了byte[]数组。
        System.out.println(new String(bytes));
        bytes[2]='a';
        //打印了50 51 97 53 54 55 56 57 57,证明了我们对byte[]数组操作影响了ByteBuffer。
        bufferDetails(buffer);
    }

打印结果

ByteBuffer常用方法与分析_第4张图片

总结

区分读模式和写模式的标准在于limit属性,如果ByteBuffer存在剩余空间,则:

  • limit=capacity表示当前为写模式
  • limit=数据量表示当前模式为读模式

你可能感兴趣的:(Netty,ByteBuffer,ByteBuffer读写模式,网络编程基础)