如何使用 Java 中 缓冲区类 Buffer

简介: # 如何使用 Java 中 缓冲区类 Buffer ## 1. 什么是Buffer 缓冲区缓冲区(Buffer):就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区 缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个数组,该对象提供了一组方法,可以更轻松地使用内存块## 2.Buffer及其常用子类从 JDK1.4开始,提供使用Buffer类![image-20220502214516083](https://yygh-sz.oss-cn-beijing.aliyuncs.com/image-2022

如何使用 Java 中 缓冲区类 Buffer

1. 什么是Buffer 缓冲区

缓冲区(Buffer):就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区 缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个数组,该对象提供了一组方法,可以更轻松地使用内存块

2.Buffer及其常用子类

从 JDK1.4开始,提供使用Buffer类

image-20220502214516083

3.Buffer 相关API介绍

方法名 说明
int position() / position(int newPosition) 获得当前要操作的索引/修改当前要操作的索引位置
int limit() / limit(int newLimit) 最多能操作到哪个索引/修改最多能操作的索引位置
int capacity() 返回缓冲区的总长度
int remaining() /boolean hasRemaining() 还有多少能操作索引个数/是否还有能操作
put(byte b)/put(byte[] src) 添加一个字节/添加字节数组
flip() 切换读模式 limit设置position位置, position设置0
rewind() 将position设置为0,可以重复读
clear() 换写模式 position设置为0 , limit 设置为 capacity
get() 读一个字节
get(byte[] dst) 读多个字节
get(int index) 读指定索引的字节

image-20220503100537464

        ByteBuffer bbf = ByteBuffer.allocate(10);

        System.out.println("当前索引"+bbf.position());
        System.out.println("最大索引位置"+bbf.limit());
        System.out.println("能操作索引长度"+bbf.remaining());
        System.out.println("缓冲区总长度"+bbf.capacity());

image-20220503100622836

4.创建Buffer实例

方式一 : 指定缓冲区的容量

        //方式一: 指定容量为10个字节
        ByteBuffer allocate = ByteBuffer.allocate(10);
public static ByteBuffer allocate(int capacity)分配一个新的字节缓冲区。 
新缓冲区的位置将为零,其限制将为其容量,其标记将不定义,并且其每个元素将被初始化为零。 它将有一个backing array ,其array offset将为零。 

参数 
capacity - 新的缓冲区的容量,以字节为单位 
结果 
新的字节缓冲区 
异常 
IllegalArgumentException - 如果 capacity是负整数 

方式二: 指定缓存区内容与容量

        //方式二: 指定数组内容
        ByteBuffer wrap = ByteBuffer.wrap("abc".getBytes());
public static ByteBuffer wrap(byte[] array)将一个字节数组包装到缓冲区中。 
新的缓冲区将由给定的字节数组支持; 也就是说,对缓冲区的修改将导致数组被修改,反之亦然。 新缓冲区的容量和限制将为array.length ,其位置将为零,其标志将不确定。 其backing array将是给定的数组,其array offset>将为零。 

参数 
array - 将返回此缓冲区的数组 
结果 
新的字节缓冲区 

5. Buffer 的增查改

增 与 修改

image-20220502215942045

        ByteBuffer bbf = ByteBuffer.allocate(10);
        //添加一个字节
        bbf.put((byte) '1');
        //添加一个字节数组
        bbf.put("234".getBytes());

修改 :

image-20220503101155062

        ByteBuffer bbf = ByteBuffer.wrap("abcd".getBytes());

        byte b = bbf.get(0);
        System.out.println("b = " + b);
        bbf.put(0,(byte) 48);
         b = bbf.get(0);
        System.out.println("b = " + b);

如何查找缓冲区中的内容呢 ? 可以调用 get 方法

image-20220502220508296

一次读一个字节

        //切换到读模式
        bbf.flip();
        //获取缓冲区中的内容

        while (bbf.hasRemaining()) {
            System.out.println("bbf.get() = " +bbf.get());
        }

一次读一个字节数组

        //切换到读模式
        bbf.flip();
        //获取缓冲区中的内容

        byte[] bytes = new byte[9];
        bbf.get(bytes,0,bbf.remaining());
        System.out.println(new String(bytes));

6.读与写模式

6.1 flip 读模式

image-20220503101934821

当调用 flip() 方法,切换为读模式时 limit 来到当前 position 的位置 而 position 将回到 起始位置

        ByteBuffer bbf = ByteBuffer.allocate(10);
        for (int i = 0; i < 3; i++) {
            bbf.put((byte) i);
        }
        System.out.println("当前索引 = "+bbf.position());
        System.out.println("当前limit = "+bbf.limit());
        System.out.println("切换读模式");
        bbf.flip();
        System.out.println("当前索引 = "+bbf.position());
        System.out.println("当前limit = "+bbf.limit());
当前索引 = 3
当前limit = 10
切换读模式
当前索引 = 0
当前limit = 3

调用 rewind() 方法 可将 position 再次移到起始位置 实现重复读

image-20220503103133669

6.2 clear 写模式

image-20220503102209093

当调用 clear() 方法,切换为写模式时 limit 来到当前 capacity 的位置 而 position 将回到 起始位置

此时如果进行添加操作,原值将被覆盖

ByteBuffer bbf = ByteBuffer.allocate(10);
        for (int i = 0; i < 3; i++) {
            bbf.put((byte) i);
        }
        System.out.println("当前索引 = "+bbf.position());
        System.out.println("当前limit = "+bbf.limit());
        System.out.println("切换读模式");
        bbf.flip();  //切换读模式
        System.out.println("当前索引 = "+bbf.position());
        System.out.println("当前limit = "+bbf.limit());

        while (bbf.hasRemaining()){
            System.out.println(bbf.get());
        }
       
        bbf.clear();//切换写模式
        System.out.println("切换写模式");
        System.out.println("当前索引 = "+bbf.position());
        System.out.println("当前limit = "+bbf.limit());
        for (int i = 2; i >=0; i--) {
            bbf.put((byte) i);
        }
        System.out.println("3次添加操作后的索引 = "+bbf.position());
        System.out.println("3次添加操作后的limit = "+bbf.limit());
        bbf.flip();//再次切换读模式,原值已经被替换
        while (bbf.hasRemaining()){
            System.out.println(bbf.get());
        }
当前索引 = 3
当前limit = 10
切换读模式
当前索引 = 0
当前limit = 3
0
1
2
切换写模式
当前索引 = 0
当前limit = 10
3次添加操作后的索引 = 3
3次添加操作后的limit = 10
2
1
0

7. 总结

  1. capacity:容量 limit: 界限(最多能读/写到哪里)posotion:索引位置
  2. 获取缓冲区里面数据之前,需要调用flip方法
  3. 再次写数据之前,需要调用clear方法,但是数据还未消失,等再次写入数据,被覆盖了才会消失。
相关文章
|
1天前
|
存储 Java
Java基础教程(7)-Java中的面向对象和类
【4月更文挑战第7天】Java是面向对象编程(OOP)语言,强调将事务抽象成对象。面向对象与面向过程的区别在于,前者通过对象间的交互解决问题,后者按步骤顺序执行。类是对象的模板,对象是类的实例。创建类使用`class`关键字,对象通过`new`运算符动态分配内存。方法包括构造函数和一般方法,构造函数用于对象初始化,一般方法处理逻辑。方法可以有0个或多个参数,可变参数用`类型...`定义。`this`关键字用于访问当前对象的属性。
|
5天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
10 0
|
5天前
|
Java
Java 15 神秘登场:隐藏类解析未知领域
Java 15 神秘登场:隐藏类解析未知领域
10 0
|
7天前
|
安全 Java
append在Java中是哪个类下的方法
append在Java中是哪个类下的方法
21 9
|
7天前
|
JavaScript Java 测试技术
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
25 0
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
|
8天前
|
存储 安全 Java
java多线程之原子操作类
java多线程之原子操作类
|
10天前
|
Java
Java中的多线程实现:使用Thread类与Runnable接口
【4月更文挑战第8天】本文将详细介绍Java中实现多线程的两种方法:使用Thread类和实现Runnable接口。我们将通过实例代码展示如何创建和管理线程,以及如何处理线程同步问题。最后,我们将比较这两种方法的优缺点,以帮助读者在实际开发中选择合适的多线程实现方式。
19 4
|
10天前
|
Java
在Java中,多态性允许不同类的对象对同一消息做出响应
【4月更文挑战第7天】在Java中,多态性允许不同类的对象对同一消息做出响应
16 2
|
15天前
|
Java
Java通过反射获取类调用方法
Java通过反射获取类调用方法
18 0
|
16天前
|
Java 关系型数据库 数据库连接
52 类 110 个常用 Java 组件和框架整理
52 类 110 个常用 Java 组件和框架整理
13 0