NIO数据容器buffer简单示例

本文深入探讨Java NIO中的ByteBuffer使用,包括其基本属性、分配、分片、只读及直接缓冲区的概念与操作。通过示例代码,详细解释如何进行数据的读写、分片、以及不同类型的缓冲区应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们都直到,BIO 面向流的,而NIO 则是面向缓冲区的。所以我们需要一个数据容器来作为缓冲来存储即将写入或者读入的数据。对于java 的基本数据类型都有一种对应的buffer,通过我们使用最多的是byteBuffer

下面我们来演示下ByteBuffer 的使用情况:

public class ByteBufferDemo {
    public static void main(String[] args) {
        ByteBuffer b = ByteBuffer.allocate(26);
        for(int i = 65;i<b.capacity() + 65;i++){
            //往buffer添加一个字节的数据  
            b.put((byte) i);
        }
        System.out.println("position:" + b.position() + ",limit:"+ b.limit());
        //切换到读模式   将limit 置为当前的position  然后position = 0 
        b.flip();

        byte[] b1 = new byte[26];

        System.out.println("position:" + b.position() + ",limit:"+ b.limit());

        //将数据读入到数组中  读取从position到limit之间的值  如果可读的长度小于 b1的长度,那么将会抛出  BufferUnderflowException
        b.get(b1);
        
        System.out.println(new String(b1));
    }
}

上面的代码我们演示了向缓冲区中添加了 26个大写的英文字母。运行该方法我们可以得到以下输出:

position:26,limit:26
position:0,limit:26
ABCDEFGHIJKLMNOPQRSTUVWXYZ

这里我们只进行一次读写,如果我们还需再次写入数据该怎么办?

调用buffer的clear()方法,将其所有的位置属性恢复到初始状态。clear方法的源码如下:

    public Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }
buffer的四个基本属性讲解:
  • mark:标记,调用mark()来设置mark=position,再调用reset()可以position恢复到标记的位置
  • position:位置,下一个读或者写的索引,每次读写缓冲区数据时都会改变该值
  • limit:表示缓冲区的当前终点,不能对超过该位置区域进行读写,且极限是可以修改的。
  • capacity:容量,即可以容纳的最大数据量,在创建的时候确定不能被修改

以上的这几个属性遵循的恒等式:

mark <= position <= limit < capacity

缓冲区的分配

我们可以直接调用allocation()方法来直接创建一个缓冲区。对于ByteBuffer``来说,就是实例化HeapByteBuffer 对象。此外,我们还可以通过wrap方法将一个现有的数据包装成buffer对象,实际上也是创建了一个HeapByteBuffer 对象。

@Test
public void testAllocation(){
    
    //1、直接分配缓冲区
    ByteBuffer byteBuffer = ByteBuffer.allocate(26);
    
    // 2、将现有的数组包装成一个buffer
    ByteBuffer wrap = ByteBuffer.wrap(new byte[20]);
    
    

}

缓冲区分片

NIO中,我们还可以对一个缓冲区进行分片。即在现有的缓冲区上切出一个新的缓冲区,他们共享底层的数据,也就是说子缓冲区相当于原缓冲区的一个视图窗口。

    /**
     * 测试缓冲区分片  ,子缓冲区和父缓冲区是共享数据的
     */
    @Test
    public void testView(){
        ByteBuffer byteBuffer = ByteBuffer.allocate(26);
        for (byte i = 65;i<65+byteBuffer.capacity();i++){
            byteBuffer.put(i);
        }
        byteBuffer.flip();
        //获取一个子缓冲区
        ByteBuffer slice = byteBuffer.slice();


        byte[] read = read(byteBuffer);

        System.out.println(new String(read));

        //更改子缓冲区的中数值    这里放入的是26个小写字母
        for(byte i=97;i<97+slice.capacity();i++){
            slice.put(i);
        }

       byteBuffer.position(0);
        byte[] bytes = read(byteBuffer);
        //如果打印出来的是小写字母,那么说明他们是共享同一个数组
        System.out.println(new String(bytes));

    }


    /**
     * 从buffer将数据读取到数组中
     * @param buffer
     * @return
     */
    public static  byte[] read(ByteBuffer buffer){
        byte[] bytes = new byte[buffer.limit() - buffer.position()];
        buffer.get(bytes);
        return  bytes;
    }

只读缓冲区

只读缓冲区是一个只能读取不能写入的buffer。通过调用缓冲区的asReadOnlyBuffer()方法来获取。如果向一个只读的buffer中写入数据,将会抛java.nio.ReadOnlyBufferException

    @Test
    public void testReadOnly(){
        ByteBuffer buffer = ByteBuffer.allocate(26);
        for(byte i= 65;i<65 + 20;i++){
            buffer.put(i);
        }

        ByteBuffer readOnly = buffer.asReadOnlyBuffer();
        
        //  抛出  java.nio.ReadOnlyBufferException 
        readOnly.put((byte) 97);

    }

直接缓冲区

直接缓冲区是用来加快I/O速度,使用特殊方式分配内存的缓冲区。通常是通过调用al

    /*
    测试直接缓冲区
     */
    @Test
    public void testAllocateDirect(){
        ByteBuffer buffer = ByteBuffer.allocateDirect(26);

        for(byte i= 65;i<65 + buffer.capacity();i++){
            buffer.put(i);
        }

        buffer.flip();
        byte[] read = read(buffer);

        System.out.println(new String(read));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值