【NIO】4. ByteBuffer的几个重要方法

java.nio.ByteBuffer常用方法详解 一、前言 在Java nio中,主要有三大组件:Buffer,Channel和Selector。这三者之间的关系可以按照如下方式进行理解: Buffer提供了一个字节缓冲区,其可以不断的从Channel中读取接收到的数据。Buffer的优点主要在于其提供了一系列的Api,能够让用户更方便的对数据进行读取和写入; Channel简单来说就是一个信道,也就是客户端与服务器的一个连接,而且每个客户端都会对应一个Channel对象; Selector是Java nio能够支持高并发数据处理一个关键,其核心理 阅读详情

1. 分配内存(allocate vs allocateDirect)

从内存中划分一块区域给ByteBuffer有两种方式

  • 方式一:从【JVM堆内存】中分配;
  • 方式二:从【直接内存】中分配(操作系统内存);

JVM堆内存的读写效率比直接内存低;因为

  • JVM堆内存多一次数据拷贝;
  • 堆内存受到JVM垃圾回收的影响;
public static void main(String[] args) {

        // 从【JVM堆内存】中分配
        ByteBuffer allocate = ByteBuffer.allocate(16);

        // 从【直接内存】中分配(物理内存)
        ByteBuffer allocateDirect = ByteBuffer.allocateDirect(16);

        System.out.println(allocate.getClass()); // class java.nio.HeapByteBuffer
        System.out.println(allocateDirect.getClass()); // class java.nio.DirectByteBuffer

    }
对比项allocate(堆)allocateDirect(直接)
内存位置JVM 堆堆外(OS 内存)
分配/回收速度快慢
I/O 性能较低(需复制)高(零拷贝)
适用场景普通场景高频 I/O、大文件

2. 向Buffer写入数据

2.1 从Channel中读取数据并写入Buffer

public static void main(String[] args) {
        try(FileInputStream fileInputStream = new FileInputStream("src/main/resources/Buffer01_HelloWorld.txt")) {
            // 获取文件channel
            FileChannel channel = fileInputStream.getChannel();

            // 从内存中分配一个buffer,大小为10个字节
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);

            // 从channel中读取数据,并写到buffer中
            channel.read(byteBuffer);


        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

2.2 调用Buffer的put方法

public static void main(String[] args) {
        // 从内存中分配一个buffer,大小为10个字节
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        // 写入一个byte
        byteBuffer.put((byte) 1);

        // 写入byte数组
        byteBuffer.put("abc".getBytes(StandardCharsets.UTF_8));
    }

3. 从Buffer中读取数据

注意:在从buffer中读取数据之前,必须调用flip方法切换到读模式!

3.1 从Buffer中读取数据,写入Channel

public static void main(String[] args) {
        try (FileOutputStream fileOutputStream = new FileOutputStream("src/main/resources/test.txt")) {
            // 获取文件channel
            FileChannel channel = fileOutputStream.getChannel();

            // 从内存中分配一个buffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);

            // 向buffer中写入数据
            byteBuffer.put("abc".getBytes(StandardCharsets.UTF_8));

            // 切换到buffer的读模式
            byteBuffer.flip();

            // 从buffer中读取数据,写入channel
            int write = channel.write(byteBuffer);

            // 打印写入的字节数:3
            System.out.println(write);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

3.2 调用Buffer的get(index)方法,获取指定索引位置的数据

该方法不会移动position的位置,就像操作数组一样,可以重复读取;

public static void main(String[] args) {
        // 从内存中分配一个buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        // 向buffer中写入数据
        byteBuffer.put("abc".getBytes(StandardCharsets.UTF_8));

        // 切换到buffer的读模式
        byteBuffer.flip();

        // get(index),不会移动position的位置,就像操作数组一样,可以重复读取;
        System.out.println(byteBuffer.get(0)); // 97
        System.out.println(byteBuffer.get(1)); // 98
        System.out.println(byteBuffer.get(2)); // 99
        System.out.println(byteBuffer.get(0)); // 97
    }

3.3 调用Buffer的get()方法,获取当前position位置的数据

该方法会让position移动,当读取完Buffer中的数据后,position也移动到Buffer的末尾,此时再读取就会出异常:java.nio.BufferUnderflowException

public static void main(String[] args) {
        // 从内存中分配一个buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        // 向buffer中写入数据
        byteBuffer.put("abc".getBytes(StandardCharsets.UTF_8));

        // 切换到buffer的读模式
        byteBuffer.flip();

        // get(),会让position移动
        System.out.println(byteBuffer.get());
        System.out.println(byteBuffer.get());
        System.out.println(byteBuffer.get());

        System.out.println(byteBuffer.get());
        
    }

输出结果

"C:\Program Files\Java\jdk-1.8\bin\java.exe" ...
97
98
99
Exception in thread "main" java.nio.BufferUnderflowException
	at java.nio.Buffer.nextGetIndex(Buffer.java:524)
	at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:138)
	at com.xxx.xxx.main(xxx.java:26)

Process finished with exit code 1

如果想重复读取数据,可以调用rewind方法,将position重新置为0;

public static void main(String[] args) {
        // 从内存中分配一个buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        // 向buffer中写入数据
        byteBuffer.put("abc".getBytes(StandardCharsets.UTF_8));

        // 切换到buffer的读模式
        byteBuffer.flip();

        // get(),会让position移动
        System.out.println(byteBuffer.get()); //97
        System.out.println(byteBuffer.get()); //98
        System.out.println(byteBuffer.get()); //99

        // 调用rewind方法,将position重新置为0
        byteBuffer.rewind();

        System.out.println(byteBuffer.get()); //97

    }

4. mark & reset

  • mark():使用变量mark,记住当前position的值;
  • reset():将position的值重新设为mark;
public static void main(String[] args) {
        // 从内存中分配一个buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);

        // 向buffer中写入数据
        byteBuffer.put("abc".getBytes(StandardCharsets.UTF_8));

        // 切换到buffer的读模式
        byteBuffer.flip();

        // 使用变量mark,记住当前position的值,当前position 即0;
        System.out.println(byteBuffer.mark());

        // get(),会让position移动
        System.out.println(byteBuffer.get());
        System.out.println(byteBuffer.get());
        System.out.println(byteBuffer.get());

        // 将position的值重新设为mark,即0;
        System.out.println(byteBuffer.reset());

        // 此时可以再次从头读取
        System.out.println(byteBuffer.get());

    }

输出结果

"C:\Program Files\Java\jdk-1.8\bin\java.exe" ...
java.nio.HeapByteBuffer[pos=0 lim=3 cap=10]
97
98
99
java.nio.HeapByteBuffer[pos=0 lim=3 cap=10]
97

Process finished with exit code 0

5. 将字符串转为buffer

5.1 将字符串转为字节数组,写入ByteBuffer

public static void main(String[] args) {

        // 从内存中分配一个buffer
        ByteBuffer buffer = ByteBuffer.allocate(16);

        // 将字符串转为字节数组,写入buffer
        buffer.put("hello".getBytes(StandardCharsets.UTF_8));

        // 切换到读模式
        buffer.flip();

        System.out.println(buffer.get()); //104
        System.out.println(buffer.get()); //101
        System.out.println(buffer.get()); //108
        System.out.println(buffer.get()); //108
        System.out.println(buffer.get()); //111

    }

5.2 使用Charset的encode方法,将字符串包装成ByteBuffer

注意:在从buffer中读取数据之前,必须调用flip方法切换到读模式,

通过StandardCharsets.UTF_8.encode方法,返回ByteBuffer对象之前,已经调用过flip方法了;但是为了保证已经切换到读模式,最好再读取数据之前,显式调用flip方法;

public static void main(String[] args) {

        // 使用Charset的encode方法,将字符串包装成ByteBuffer
        // 返回ByteBuffer对象之前,已经调用过flip方法
        ByteBuffer buffer = StandardCharsets.UTF_8.encode("hello");

        // 显式调用flip方法,确保切换到读模式
        buffer.flip();

        System.out.println(buffer.get()); //104
        System.out.println(buffer.get()); //101
        System.out.println(buffer.get()); //108
        System.out.println(buffer.get()); //108
        System.out.println(buffer.get()); //111

    }

5.3 使用ByteBuffer的wrap方法,将字符串包装成ByteBuffer

public static void main(String[] args) {

        // 使用ByteBuffer的wrap方法,将字符串包装成ByteBuffer
        ByteBuffer buffer = ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8));

        // 切换到读模式
        buffer.flip();

        System.out.println(buffer.get()); //104
        System.out.println(buffer.get()); //101
        System.out.println(buffer.get()); //108
        System.out.println(buffer.get()); //108
        System.out.println(buffer.get()); //111

    }

6. 分散读 & 集中写(了解)

6.1 分散读

读取文件中的内容,写入多个Buffer中。

文件内容:

owntwothree
public static void main(String[] args) {
        try (FileInputStream fileInputStream = new FileInputStream("test.txt")) {

            FileChannel channel = fileInputStream.getChannel();
            
            ByteBuffer buffer1 = ByteBuffer.allocate(3);
            ByteBuffer buffer2 = ByteBuffer.allocate(3);
            ByteBuffer buffer3 = ByteBuffer.allocate(5);
            
            long read = channel.read(new ByteBuffer[]{buffer1, buffer2, buffer3});
            System.out.println("read bytes: " + read); // 11
            // 第一个buffer写入【one】
            // 第二个buffer写入【two】
            // 第三个buffer写入【three】

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

6.2 集中写

将多个Buffer中的数据,写入一个文件

public static void main(String[] args) {
        ByteBuffer buffer1 = StandardCharsets.UTF_8.encode("hello"); //5 bytes
        ByteBuffer buffer2 = StandardCharsets.UTF_8.encode("world"); //5 bytes
        ByteBuffer buffer3 = StandardCharsets.UTF_8.encode("你好"); //6 bytes

        try (FileOutputStream fileOutputStream = new FileOutputStream("text.txt")) {
            FileChannel channel = fileOutputStream.getChannel();

            long write = channel.write(new ByteBuffer[]{buffer1, buffer2, buffer3});
            System.out.println("write bytes: " + write); //16
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
Java NIO学习笔记:深入解析ByteBuffer用法 Java NIO是一种基于通道(Channel)和缓冲区(Buffer)的I/O操作方法论,它提供了与传统IO不同的I/O操作方式。传统IO是基于流的,读写操作是阻塞式的,而Java NIO则支持面向缓冲区的(Buffer-oriented)、基于通道的(Channel-based)I/O操作,读写操作是非阻塞的。Java NIO的引入旨在提高网络和文件I/O的性能。不同于流I/O,NIO允许用户指定何时开始I/O操作,何时结束,以及在什么条件下进行,提供了一种“选择就绪”的I/O操作模式。 阅读详情

相关推荐

NIO(byteBuffer)按行读取文件

使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com

ByteBuffer的使用

ByteBuffer的使用以及其中的方法

z318913的博客 3222

高通camera:PDAF的配置与测试

确认相关log日志都已经打开了之后,判断是在3A算法中没有应用到PDAF,可能是之前在调试AF效果的时候关闭了PDAF,打开效果文件对应的文件夹,在\kamorta_lce_S5K3P9\Scenario.Default\XML\STATS。在log中搜索af_pdaf_proc_pd_single,这个函数是pdaf算法中的,源码被封装了,这里看不到,因此只能通过log打印出来的参数来分析pd是否正确,主要参数有pd ,defocus,confidence。PDAF的配置与测试。

arvin_xiong的博客 2489

ByteBuffer

ByteBuffer有两种类型,一种是创建ByteBufferByteBuffer b1 = ByteBuffer.allocate(size);进入 ByteBuffer的allocate方法: public static ByteBuffer allocate(int capacity) { ... return new HeapByteBuffer(capaci

lbknxy的专栏 2047

《Ventoy 制作系统安装 U 盘的具体步骤》

然后您可以在电脑的磁盘管理中对 U 盘进行快速格式化,选择 FAT32 或 NTFS 文件系统。至此,Ventoy 系统安装 U 盘就制作完成了。您可以在需要安装系统的电脑上,从 U 盘启动,然后选择相应的系统镜像进行安装。安装完成后,将您需要的操作系统镜像文件(如 Windows、Linux 等的 ISO 格式镜像)复制到 U 盘的根目录。在安装程序中,选择您插入的 U 盘设备,确保选择正确,以免误操作。2. 确认选择的 U 盘盘符正确,防止误操作导致其他磁盘数据丢失。点击“安装”按钮,等待安装完成。

jiyiwangluokeji的博客 2670

从零到一:基于GeneMark-ES/ET的新基因组注释实战指南

本文提供了一份基于GeneMark-ES/ET的新基因组注释实战指南。详细介绍了从环境搭建、数据准备到核心运行的全流程,重点解析了ES(从头预测)与ET(结合RNA-Seq证据)两种模式的选择与操作,并分享了Perl模块依赖、并行处理等常见问题的解决方案,帮助生物信息学研究者高效完成基因预测工作。

weixin_29266647的博客 209

java bytebuffer读取_Java NIO学习笔记之二-图解ByteBuffer

ByteBuffer前前后后看过好几次了,实际使用也用了一些,总觉得条理不够清晰。《程序员的思维修炼》一本书讲过,主动学习,要比单纯看资料效果来的好,所以干脆写个详细点的文章来记录一下。概述ByteBuffer是NIO里用得最多的Buffer,它包含两个实现方式:HeapByteBuffer是基于Java堆的实现,而DirectByteBuffer则使用了unsafe的API进行了堆外的实现。这里...

weixin_28689969的博客 1616

逐行逐句进一步了解SurroundOcc(一)

通过分析中的模型构建过程,理解了从配置文件到模型实例化的整个流程。构建过程的核心是通过build和等函数,逐步将配置文件解析并生成模型的各个模块对象,最终组合成一个完整的模型结构。这一过程涉及多个类和函数的调用,其中函数是生成对象的关键,它能够从配置字典中提取必要信息并生成对应的类实例。

lovely_yoshino的博客 8112

Java中怎么创建和读写ByteBuffer?

ByteBuffer是Java中用于处理原始字节数据的类,它提供了一种灵活的方式来创建、读取和写入字节数据。

Blue92120的博客 1160

Halcon实战:5种边缘检测算子对比(Sobel、Roberts、Prewitt、Kirsch、Canny)

本文深入对比了Halcon中Sobel、Roberts、Prewitt、Kirsch和Canny五大边缘检测算子的实战表现与核心差异。通过工业图像实例与代码解析,提供了基于噪声水平、边缘连续性及实时性要求的场景化选型指南,帮助工程师精准选择最适合的算子以优化视觉检测流程。

weixin_29266007的博客 392

S32K144 UDSdoCAN 升级刷写实现笔记

本篇旨在描述如何开发“车规级”的软件升级程序,通过在S32K144平台上实现基于UDSdoCAN的刷写升级功能,带你一步步建立安全升级的“工程思维”,在这里既能收获经验还能获得工程源码、测试脚本,助你起飞,避坑提速!

汽车电子软件领域知识分享 811

ByteBuffer简单应用之ByteBuffer知多少?

Buffer 类是 java.nio 的构造基础。一个 Buffer 对象是固定数量的数据的容器,其作用是一个存储器,或者分段运输区,在这里,数据可被存储并在之后用于检索。缓冲区可以被写满或释放。对于每个非布尔原始数据类型都有一个缓冲区类,即 Buffer 的子类有:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffe

zxwei09的博客 1606

MTK(camera篇)Camera整体点亮

本文介绍了在MTK平台上添加新Camera Sensor的驱动开发流程。主要内容包括:1)MTK Camera采用HAL3架构,驱动层主要负责sensor电源控制和寄存器操作;2)详细说明了添加新sensor需要在多个文件中进行的修改,包括设备树配置、内核头文件、驱动列表、电源序列等;3)特别指出需要配置I2C地址表,并导入tuning文件和metadata文件以完善ISP处理流程。文章提供了完整的文件修改清单,涵盖了从内核层到HAL层的完整开发过程,为MTK平台Camera Sensor驱动开发提供了具体

weixin_49303682的博客 361

java.nio.ByteBuffer用法小结

文章目录简介初始化向ByteBuffer写数据手动写入数据从SocketChannel中读入数据至ByteBuffer从ByteBuffer中读数据复位position读取数据字节序处理 简介 在Java的Socket编程中,若使用阻塞式(BIO),则往往通过ServerSocket的accept()方法获取到客户端Socket之后,再使用客户端Socket的InputStream和OutputS...

水蓝城 7万+

YOLOv8 更换损失函数DIoU、EIoU、GIoU...Inner-IoU...

介绍了一些损失函数,并将其应用到yolov8训练中

分享一些自己改进代码的实例 888

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

NIO之ByteBuffer的使用

NIO之ByteBuffer的使用 NIO中有三大组件:Channel、Selector、Buffer,今天就来讲讲Buffer的使用。 Buffer的继承结构: Buffer为java中的每个数据类型都提供了对应的实现类,但是实际使用中用得最多的还是ByteBuffer。 ByteBuffer的创建 在堆上创建: log.info("freeMemory:{}MB", Runtime.getRuntime().freeMemory() / _1_MB); ByteBuffer allocate = By

morris 2万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Java NIO ByteBuffer 使用方法

OnMessage//xxxxx以前只知道 NIO 里面大量用到了 ByteBuffer ,并没有仔细了解过,这次特意学习了一下,因为JDK自带的ByteBuffer 可以切换读写两种模式加上内置很多方法组合使用,有很多约定俗成的用法,稍不注意就有可能踩坑,这也是为什么Netty里面又基于 ByteBuffer 重新封装了ByteBuf类,就是因为 JDK 自带的太难用了Java 中的 ByteBuffer 是 java.nio 包中的核心类之一,属于 New I/O (NIO) 框架。

三劫散仙 1281

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

NIO:缓冲区ByteBuffer方法讲解

       NIO是jdk1.4后引入,是为了解决普通IO效率慢的问题。NIO将最耗时的IO操作(提取和填充缓冲区)转移回操作系统,让操作系统来完成这个操作因此可以极大的提高效率。NIO是以块为单位处理数据,传统IO是以字节为单位,所以NIO更快。       &nb...

博客 1584

java nio ByteBuffer的使用

1、介绍 Buffer是nio包的一个抽象类,作为java nio的三大组件(Buffer、Channel,Selector)之一,在java nio网络编程中尤为重要。 Buffer提供了一个字节缓冲区,配合Channel使用,可以从Channel中读取或写入数据。 2、结构 属性介绍 以ByteBuffer为例,其包括5个主要的属性:hb、position、limit、capacity、mark。 hb:ByteBuffer类有一个byte数组变量hb,此数组里面存放的就是实际的字节数据。 capaci

xiao_yu_gan的博客 3852

【源码解析】Java NIO 包中的 ByteBuffer

上一篇文章我们介绍了最底层的 Buffer,那么这篇文章就要介绍下 Buffer 的【源码解析】Java NIO 包中的 Buffer上面就是 Buffer 的继承结构,当然 Buffer 的子类肯定不会只有这么点,比如下面的图:只不过上面图中就给了几个基本 Buffer 的实现类,可以看到几个重要的实现类都是ByteBuffer的子类,这几个实现类也是我们要介绍的重点,只不过这篇文章我们先介绍 ByteBuffer。

Jwasx的博客 1493

Java NIO ByteBuffer读取文件

FileChannel 和 ByteBuffer 从JDK1.4以后就提供java.nio的包,nio主要提供字节与字符的映射、内存映射文件和文件加锁机制 其中内存映射文件在读取大文件时可能会用上,因为内存映射不是直接把文件加载到JVM内存空间 而是借用操作系统对文件的读取,这经历了由当前Java态进入到操作系统内核态,再由操作系统读取文件, 并返回数据到当前Java态的过程。由Jav

影魔的专栏 2万+

NIO之ByteBuffer

聊聊ByteBuffer

爪哇岛咖啡种植农场 1336

Java NIO 总结: ByteBuffer类介绍

ByteBuffer是Java NIO包中的一个类,它实现了Buffer接口,是处理字节数据的基础类。ByteBuffer类提供了多种方法,用于读取和写入字节数据,以及管理缓冲区的状态。ByteBuffer类支持多种数据类型,包括字节、字符、短整型、整型、长整型、浮点型和双精度浮点型等。ByteBuffer内部使用一个字节数组(byte[])来存储数据,通过操作数组中的索引位置来实现数据的读写。ByteBuffer类提供了多种方法,用于读取和写入字节数据,以及管理缓冲区的状态。

码到三十五 1653

Java NIO ByteBuffer 详解

ByteBuffer 是 Buffer 的一个具体实现,专门用于存储和操作字节数据。它提供了高效的、基于内存的 I/O 数据处理方式。Buffer 类是构建 Java NIO 的基础,其中 ByteBuffer 类是 Buffer 子类中最受欢迎的。这是因为字节类型是最通用的类型。例如,我们可以在 JVM 中使用字节来组成其他非布尔基元类型。另外,我们可以使用字节在 JVM 和外部 I/O 设备之间传输数据。

学而时习之,不亦说乎?温故而知新,可以为师矣! 1760

Nio ByteBuffer组件读写指针切换原理与常用方法

ByteBuffer ByteBuffer在Nio中用的比较多,所以需要对它也要有一定的了解 ByteBuffer的使用步骤: 向buffer中写入数据,例如调用channel.read(buffer); 调用buffer.flip()切换至读模式 从buffer中读取数据,例如调用buffer.get(); 调用buffer.clear()或者compact()切换至写状态 重复1~4步骤 那么为什么使用要按照这个步骤去使用ByteBuffer并且要切换读写模式嘞? 内部结构 首先ByteBuffer

qq_44027353的博客 1812

区别NIO的ByteBuffer的get()与get(index)方法

先啰嗦一点废话,之前代码遇到错误,第一时间去百度,这次选择了阅读源码。然后真的是茅塞顿开,理解的更加深刻透彻,也节约了时间。然后考虑到源码都是英文的,可能阅读有困难,这时候就要推荐一个插件了==> Translation 背景 是在了解NIO的字符集Charset时遇到的问题。代码如下: @Test public void CharacterEncodingTest() thr...

litblue'blog 4763
上一篇: 【NIO】3.2 ByteBuffer的原理-AI参考
下一篇: 【NIO】5. FileChannel的基本用法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值