02 Java NIO 缓冲区buffer详解 设置缓冲区大小;数据存入缓冲区;读写模式的切换;从缓冲区读取数据

本文详细介绍了Java NIO中的Buffer对象,包括其基本属性如容量、限制、位置和标记,常用方法如clear、flip、capacity等,以及如何通过allocate、put和get进行数据管理和转换。示例展示了如何避免BufferOverflowException并正确切换读写模式。

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

在这里插入图片描述

缓冲区 Buffer

  • 缓冲去Buffer:一个用与特定基本数据类型的容器。
  • Java nio中的Buffer主要用于与NIO通道进行交换,数据时从通道读入缓冲区,从缓冲区写入通道。
  • Buffer 就想一个数组,保存多个相同类型的数据。Buffer常用的子类:ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer;

缓冲区的基本属性

容量(capacity):表示Buffer缓冲区的最大容量,

缓冲区容量不能为负,创建后不能更改。

限制(limit):第一个不应该读取或写入的数据索引,即位于limit后的数据不可读写。

缓冲去的限制不能为负,不能大于其容量capacity。

位置(position):洗一个要读取或写入的数据的索引。

缓冲去的位置不能为负,不能大于其限制limit。

标记(mark)与 重复(reset):标记时一个索引,通过Buffer中的mark()方法指定Buffer中一个特定的位置position,之后通过调用reset()方法恢复到这个位置position。

标记、位置、限制、容量遵守以下不变式: 0 <= mark <= position <= limit <= capacity

buffer缓冲区常用方法

方 法描 述
Buffer clear()清空缓冲区并返回对缓冲区的引用
Buffer flip()将缓冲区的界限设置为当前位置,并将当前位置充值为 0
int capacity()返回 Buffer 的 capacity 大小
boolean hasRemaining()判断缓冲区中是否还有元素
int limit()返回 Buffer 的界限(limit) 的位置
Buffer limit(int n)将设置缓冲区界限为 n, 并返回一个具有新 limit 的缓冲区对象
Buffer mark()对缓冲区设置标记
int position()返回缓冲区的当前位置 position
Buffer position(int n)将设置缓冲区的当前位置为 n , 并返回修改后的 Buffer 对象
int remaining()返回 position 和 limit 之间的元素个数
Buffer reset()将位置 position 转到以前设置的 mark 所在的位置
Buffer rewind()将位置设为为 0, 取消设置的 mark

缓冲区的管理方式

  1. 通过allocate()方法分配一个指定大小的缓冲区
  2. put() 存入数据到缓冲区中
  3. get() 读取缓冲区中的数据
  4. flip快速反转,原缓冲区属于写模式,使用flip()方法后,切换读取数据模式(原缓冲区是读模式,切换后为写模式)。

在这里插入图片描述

示例

package com.nio;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

public class NioBufferBased {
    public static void main(String[] args) {
        bufferMethod();
        throwBufferOverflowException();

    }

    /**
     * nio buffer缓冲区常用方法
     * allocate() 分配缓冲区大小
     * put() 存入数据到缓冲区中
     * flip() 读写模式反转
     * get() 读取缓冲区数据
     *
     */
    public static void bufferMethod(){
        String str = "12345";

        // 1:分配一个指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(10);
        printCapacityLimitPosition(buf.capacity(), buf.limit(), buf.position());

        // 2:利用 put() 存入数据到缓冲区中
        buf.put(str.getBytes(StandardCharsets.UTF_8));
        printCapacityLimitPosition(buf.capacity(), buf.limit(), buf.position());

        // 3:flip快速反转,原缓冲区属于写模式,使用flip()方法后,切换读取数据模式(原缓冲区是读模式,切换后为写模式。)
        buf.flip();
        printCapacityLimitPosition(buf.capacity(), buf.limit(), buf.position());

        // 4. 利用 get() 读取缓冲区中的数据
        byte[] dst = new byte[buf.limit()];
        buf.get(dst);
        System.out.println(new String(dst, 0, dst.length));
        printCapacityLimitPosition(buf.capacity(), buf.limit(), buf.position());

        // 缓冲区目前处于读模式,使用put()写入方法将报错 java.nio.BufferOverflowException
//        buf.put("abc".getBytes(StandardCharsets.UTF_8));

        // 如果想接着写入数据,需要使用flip()方法
        buf.flip();
        printCapacityLimitPosition(buf.capacity(), buf.limit(), buf.position());
        buf.put("abc".getBytes(StandardCharsets.UTF_8));
        printCapacityLimitPosition(buf.capacity(), buf.limit(), buf.position());
    }

    /**
     * BufferOverflowException 异常
     * 写模式下,不能使用读取方法
     * 读模式下,不能使用写入方法
     */
    public static void throwBufferOverflowException(){
        // 1:分配一个指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(10);

        // 2:利用 put() 存入数据到缓冲区中
        buf.put("hello".getBytes(StandardCharsets.UTF_8));

        // 3:flip快速反转,原缓冲区属于写模式,使用flip()方法后,切换读取数据模式(原缓冲区是读模式,切换后为写模式。)
        buf.flip();

        // 4. 利用 get() 读取缓冲区中的数据
        byte[] dst = new byte[buf.limit()];
        buf.get(dst);
        System.out.println(new String(dst, 0, dst.length));

        // 缓冲区目前处于读模式,使用put()写入方法将报错 java.nio.BufferOverflowException
        //buf.put("abc".getBytes(StandardCharsets.UTF_8));

        // 如果想接着写入数据,需要使用flip()方法
        buf.flip();
        buf.put("abc".getBytes(StandardCharsets.UTF_8));
    }


    /**
     * 打印输出 capacity limit position
     *
     * @param capacity 容量
     * @param limit    限制
     * @param position 位置
     */
    public static void printCapacityLimitPosition(int capacity, int limit, int position) {
        System.out.print("Buffer capacity:" + capacity + "; ");
        System.out.print("limit:" + limit + "; ");
        System.out.print("position: " + position + "; ");
        System.out.println();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EngineerForSoul

你的鼓励是我孜孜不倦的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值