Java NIO笔记(二):NIO Buffer(缓冲区)之基础

《Java NIO》:Channel and Buffer (通道和缓冲区) 《Java NIO》:Channel and Buffer (通道和缓冲区)从今天开始,自己将会了解下Java NIO的相关知识,以及会看下相关的类库源码。和往常自己学习新知识之前,自己都会阅读网上的一些博文和资料,以使自己对这一块的知识有一个大致的了解,然后再按照自己感兴趣的点来研究一点点知识。关于Java NIO这一块的知识,也是如此。关于Java NIO涉及到三个重要的概念:1、Chan 阅读详情

        缓冲区(Buffer)就是在内存中预留指定字节数的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区;在Java NIO中,缓冲区的作用也是用来临时存储数据,可以理解为是I/O操作中数据的中转站。缓冲区直接为通道(Channel)服务,写入数据到通道或从通道读取数据,这样的操利用缓冲区数据来传递就可以达到对数据高效处理的目的。在NIO中主要有八种缓冲区类(其中MappedByteBuffer是专门用于内存映射的一种ByteBuffer):

缓冲区是包在一个对象内的基础数据的数组,Buffer类相比一般简单数组而言其优点是将数据的内容和相关信息放在一个对象里面,这个对象提供了处理缓冲区数据的丰富的API。

所有缓冲区都有4个属性:capacity、limit、position、mark,并遵循:capacity>=limit>=position>=mark>=0,下表格是对着4个属性的解释:

属性描述
Capacity容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
Limit上界,缓冲区中当前数据量
Position位置,下一个要被读或写的元素的索引
Mark标记,调用mark()来设置mark=position,再调用reset()可以让position恢复到标记的位置即position=mark







一、创建缓冲区

        所有的缓冲区类都不能直接使用new关键字实例化,它们都是抽象类,但是它们都有一个用于创建相应实例的静态工厂方法,以ByteBuffer类为例子:

		//创建一个容量为10的byte缓冲区
		ByteBuffer buff = ByteBuffer.allocate(10);

上面代码将会从堆空间中分配一个容量大小为10的byte数组作为缓冲区的byte数据存储器。对于其他缓冲区类上面方式也适用,如创建容量为10的CharBuffer:

		//创建一个容量为10的char缓冲区
		CharBuffer buff = CharBuffer.allocate(10);

        如果想用一个指定大小的数组作为缓冲区的数据的存储器,可以使用wrap()方法:

		//使用一个指定数组作为缓冲区的存储器
		byte[] bytes = new byte[10];
		ByteBuffer buff = ByteBuffer.wrap(bytes);
上面代码中缓冲区的数据会存放在bytes数组中,bytes数组或buff缓冲区任何一方中数据的改动都会影响另一方。还可以创建指定初始位置(position)和上界(limit)的缓冲区:

		//使用一个指定数组作为缓冲区的存储器
		//并创建一个position=3,limit=8,capacity=10的缓冲区
		byte[] bytes = new byte[10];
		ByteBuffer buff = ByteBuffer.wrap(bytes, 3, 8);
下图是新创建的一个容量为10的字节缓冲区的内存图:


二、操作缓冲区

1、存取(Buffer.get() & Buffer.put())

        使用get()从缓冲区中取数据,使用put()向缓冲区中存数据。

		// 创建一个容量为10的byte数据缓冲区
		ByteBuffer buff = ByteBuffer.allocate(10);
		// 存入4次数据
		buff.put((byte) 'A');
		buff.put((byte) 'B');
		buff.put((byte) 'C');
		buff.put((byte) 'D');
		// 翻转缓冲区
		buff.flip();
		// 读取2次数据
		System.out.println((char)buff.get());
		System.out.println((char)buff.get());

        上面有提过缓冲区四个属性值一定遵循capacity>=limit>=position>=mark>=0,put()时,若position超过limit则会抛出BufferOverflowException;get()时,若position超过limit则会抛出BufferUnderflowException。

        buff.flip()是将缓冲区翻转,翻转将在下面来说。

调用put()或get()时,每调用一次position的值会加1,指示下次存或取开始的位置;

上面代码put()四次后的缓冲区内存示意图:


上面代码执行buff.flip()将缓冲区翻转后的内存示意图:


上面代码执两次get()后的缓冲区内存示意图:

        再向Buffer中读写数据时有2个方法也非常有用:

Buffer.remaining():返回从当前位置到上界的数据元素数量;

Buffer.hasRemaining():告诉我们从当前位置到上界是否有数据元素;

2、翻转(Buffer.flip())

        翻转就是将一个处于存数据状态的缓冲区变为一个处于准备取数据的状态,使用flip()方式实现翻转。Buffer.flip()的源码如下:

	public final Buffer flip() {
		limit = position;
		position = 0;
		mark = -1;
		return this;
	}
相信看到了实现的源码应该就会清楚flip()的作用了。rewind()方法与flip()很相似,区别在于rewind()不会影响limit,而flip()会重设limit属性值,Buffer.rewind()的源码如下:

	public final Buffer rewind() {
		position = 0;
		mark = -1;
		return this;
	}

3、压缩(Buffer.compact())

        压缩就是将已读取了的数据丢弃,保留未读取的数据并将保留的数据重新填充到缓冲区的顶部,然后继续向缓冲区写入数据。

		// 创建一个容量为10的byte数据缓冲区
		ByteBuffer buff = ByteBuffer.allocate(10);
		// 填充缓冲区
		buff.put((byte)'A');
		buff.put((byte)'B');
		buff.put((byte)'C');
		buff.put((byte)'D');
		System.out.println("first put : " + new String(buff.array()));
		//翻转
		buff.flip();
		//释放
		System.out.println((char)buff.get());
		System.out.println((char)buff.get());
		//压缩
		buff.compact();
		System.out.println("compact after get : " + new String(buff.array()));
		//继续填充
		buff.put((byte)'E');
		buff.put((byte)'F');
		//输出所有
		System.out.println("put after compact : " + new String(buff.array()));

以上代码打印结果:

first put : ABCD

A

B

compact after get : CDCD

put after compact : CDEF

控制台中输出内容中有正方形的乱码,是正常。因为字节缓冲区中没有赋值的内存块默认值是0,而Unicode编码中没有0编码,所以乱码。

4、标记(Buffer.mark())

        标记就是记住当前位置(使用mark()方法标记),之后可以将位置恢复到标记处(使用reset()方法恢复),mark()和reset()源码如下:

	public final Buffer mark() {
		mark = position;
		return this;
	}

	public final Buffer reset() {
		int m = mark;
		if (m < 0)
			throw new InvalidMarkException();
		position = m;
		return this;
	}
5、比较两个缓冲区是否相等

        比较两个缓冲区是否相等有2种方法:equals(Object ob) 和compareTo(ByteBuffer that),这两个方法都是在Buffer的子类中实现的。

        equals比较的两个缓冲区中的每个值,所以允许不同的Buffer对象进行比较;compareTo有类型限制,ByteBuffer只能和ByteBuffer进行比较;比较两个缓冲区实际上是比较两个缓冲区中每个缓冲区position到limit之间(不包括limit)的缓冲值。如下图:

6、批量移动缓冲区的数据

        缓冲区的目的就是高效传输数据,高效传输数据就应杜绝一个一个的传输,所以Buffer API提供了相应的方法来进行批量移动。下面是个例子:

		byte[] bytes = "hello world!".getBytes();
		// 创建一个容量等bytes容量的byte数据缓冲区
		ByteBuffer buff = ByteBuffer.allocate(bytes.length);
		//将byte数据写入缓冲区,下面代码和buff.put(bytes)效果一致
		buff.put(bytes, 0, bytes.length);
		//翻转缓冲区
		buff.flip();
		//轮询判断是否有数据,有则将缓冲区的数据批量读到array中
		byte[] array = 	new byte[bytes.length];
		while(buff.hasRemaining()){
			buff.get(array, 0, buff.remaining());
		}
		//输出冲缓冲区读出来的数据
		System.out.println(new String(array));
以上面代码为例,

写数据到缓冲区时,若bytes.length > buff.capacity()则会抛出java.nio.BufferOverflowException;

从缓冲区中读数据时,若array.length < buff.limit()则会抛出java.lang.IndexOutOfBoundsException。

7、复制缓冲区

        复制一个与源缓冲区共享数据的缓冲区,各自管理自己的属性

  • asReadOnlyBuffer():复制一个只读缓冲区
  • duplicate():复制一个可读可写的缓冲区
  • slice():复制一个从源缓冲position到limit的新缓冲区

Codesys电子凸轮从入门到应用:手把手教你用MC_CamIn/MC_CamOut实现主从轴同步 本文详细介绍了如何在Codesys平台上使用MC_CamIn和MC_CamOut功能块实现电子凸轮的主从轴同步控制。从环境配置、轴使能到凸轮表创建与动态切换,提供了完整的程序编写指南和调试技巧,帮助工程师快速掌握工业自动化中的高精度运动控制技术。 阅读详情

相关推荐

MATLAB射线追踪算法实战:从零搭建通信信号传播模型(附完整代码)

本文提供了一份详细的MATLAB射线追踪算法实战指南,指导读者从零开始搭建通信信号传播模型。内容涵盖场景建模、射线发射、路径追踪与信号计算等核心环节,并附有完整代码,帮助通信与电子工程领域的学习者和工程师快速掌握这一精确模拟电磁波传播的关键技术。

weixin_29092031的博客 196

NIO Buffer 实现原理

目前很多高性能的Java RPC框架都是基于Netty实现的,而Netty的设计原理又离不开Java NIO。本篇笔记是对NIO核心三件套:缓冲区(Buffer)、选择器 (Selector)和通道(Channel),其中之一的实现原理的学习总结。

兴趣使然的草帽路飞 1万+

水电站数字孪生:水力发电在可视化领域的应用

为智慧水坝领域提供了 B/S 架构的基于 WebGL 的图形引擎,与 GIS、粒子仿真、虚拟现实、边缘计算等技术相结合,融合多元业务系统数据,形成数字孪生界面,助力水利水电工程进一步提升数字化水平,乃至为整个工业领域添砖加瓦。

二三维数据可视化/数字孪生 2255

buffer

类进行数据读写操作时,需要确保缓冲区有足够的容量来存储数据,否则可能会发生缓冲区溢出的情况。另外,需要正确处理缓冲区的位置和限制位置,以避免数据不完整或丢失的情况。提供了一组读写方法,用于向缓冲区中写入数据或从缓冲区中读取数据。它也提供了一些属性和方法,用于管理缓冲区的状态、容量和位置等。是一个抽象的数据缓冲区,它可以存储不同类型的数据,包括字节、字符、整数、浮点数等。在这个示例中,我们首先创建了一个大小为 1024 的字节缓冲区,并使用。方法将缓冲区切换到写模式,以便我们可以继续向缓冲区中写入数据。

雅文科技的博客 501

嵌入式开发中Tab与空格混用的危害与统一规范实践

在软件工程中,代码格式一致性是保障可读性与团队协作效率的基础。从原理上看,制表符(Tab)与空格(Space)在存储与显示机制上存在本质差异:Tab是控制字符,其显示宽度取决于编辑器设置;空格则是固定宽度的字符。这种差异导致混用时会引发代码对齐错乱、版本控制冲突及跨平台兼容性问题,严重影响工程的可维护性。尤其在嵌入式开发领域,资源受限环境与高可靠性要求使得统一的编码规范更为关键。通过配置编辑器、集成clang-format等自动化工具,可以强制实现缩进风格的一致性,从而提升代码质量与团队协作效率。本文聚焦于

weixin_42545636的博客 276

Ubuntu 22.04 安装 PostgreSQL + AGE + pgvector 完全指南

本教程详细介绍了在Ubuntu 22.04服务器上安装PostgreSQL数据库,并为其添加AGE图数据库扩展和pgvector向量搜索扩展的步骤。首先,更新系统并安装PostgreSQL,然后通过源码构建并安装AGE和pgvector扩展。接着,配置PostgreSQL以使用这些扩展,并可选地允许远程连接。教程还包括创建用户、设置密码、验证安装以及安装后的优化建议。最后,提供了常见问题的解决方法。通过本教程,用户可以在同一数据库中处理关系型数据、图数据和向量数据,为现代应用程序提供强大的数据支持。

这个是个人博客,记录生活中的一些日常。 1742

NIO--Buffer

Buffer 缓冲区基础 概念上,缓冲区是包在一个对象内的基本数据元素数组。Buffer类相比一个简单数组的优点是它将关于数据的数据内容和信息包含在一个单一的对象中。Buffer类以及它专有的子类定义了一个用于处理数据缓冲区的API。 属性 所有的缓冲区都具有四个属性来提供关于其所包含的数据元素的信息。它们是: 容量(Capacity) 缓冲区能够容纳的数据元素的最大数量。这一容量...

demon7552003的小本本 511

《数学建模与数学实验》第5版 线性规划 习题3.4

1. 某鸡场有1000只鸡,用动物饲料和谷物混合喂养. 2. 某工厂用A1,A2两台机床加工B1,B2,B3三种不同零件. 3. 某工厂利用两种原料甲、乙生产$A_1、A_2、A_3$三种产品. 4. 每班的护士在值班开始时向病房报到,连续工作8个小时. 5. 某工厂生产 A1 、A2 两种型号的产品 6. 有两个煤厂A,B 7. 某工厂制造三种产品,生产这三种产品需要三种资源 8. 已知某工厂计划生产1,2,3三种产品,各产品需要在ABC设备加工。...

hexiaosi_的博客 2万+

ByteBuffer remaining 简介

现在我们获得一个buffer,即缓冲区。里面存在len长度的可用数据。我们要做的就是根据自己的协议结构将这个buffer转化为遵循我们自己的协议的packet。进而交由后面的业务逻辑代码处理。 此时我们定义自己的通信协议一个byte的包头,用于数据吧合法性验证,两byte数据包长(一般用4byte,即一个int),剩下内容为可变长度的数据包体。现在我们拿到buffer,这时候就有分包(粘包)

guomeijuan916的专栏 3万+

WSL2部署Cadence Virtuoso IC25.1:Ubuntu 26.04排障实录

WSL2以轻量虚拟机结合完整Linux内核,为Windows桌面环境提供了原生级Linux运行能力,解决了传统虚拟机资源开销大、双系统切换低效的问题。对于依赖X11图形协议、FlexNet许可服务和特定动态库的EDA工具链而言,利用WSL2部署Linux发行版需要关注系统集成、显示通路与许可连通性。从技术原理看,图形层X Server的配置、动态库依赖的补齐以及license服务的主机名解析,共同构成EDA工具在WSL2中稳定运行的关键环节。在芯片设计场景中,设计工程师常需在Windows办公机与Linux

weixin_29597551的博客 209

YOLO系列算法改进 | 自研篇 | C3k2融合SEFN空间增强前馈网络模块 | 去模糊和提升图像细节特征,精度涨点!| WACV 2025

YOLO系列算法改进 | 自研篇 | C3k2融合SEFN空间增强前馈网络模块 | 去模糊和提升图像细节特征,精度涨点!| WACV 2025 (以YOLO26最新目标检测模型为基础,C3k2融合SEFN空间增强前馈网络模块改进Backbone)

2502_91881744的博客 237

java bytebuffer 大小_Java - ByteBuffer.remaining()问题

简介:我有一个ByteBuffer,我在其中提取一些数据。之后,我想通过Socket发送这些数据。所以,我写了这样的代码:private static void serialize(ByteBuffer buffer, EmployeeData emp, CharsetEncoder encoder){// idbuffer.putInt(emp.getId());CharBuffer nameB...

weixin_29863361的博客 1503

网络安全与黑客攻防常见设备:前置机、跳板机、堡垒机与肉鸡

前置机、跳板机、堡垒机和肉鸡,这些看似冷僻的技术名词,实则是网络安全与黑客攻防战中的关键角色。它们有的守护着企业的数字Pltform,保卫网络安全;有的则成为黑客的跳板,游走于灰色地带。

网络技术联盟站 961

Java 入门指南:Java NIO —— Buffer(缓冲区)

在 NIO(New Input/Output)模型中,Buffer 是一个重要的概念,与数据打交道,用于在内存中存储数据。通过 Channel 将数据传输到 Buffer 缓冲区中,并在缓冲区内进行数据的读写操作。 Buffer 本质上是一个数组,可以存储多个相同类型的基本数据类型,如 byte、short、int、long、float、double 等。Buffer 封装了内部的数组,并提供了一些操作该数组的方法。

热带鱼的技术博客 2258

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java NIO的Buffer缓冲区和Channel通道详细总结

NIO 主要有在 NIO 中,并不是以流的方式来处理数据的,而是以 buffer 缓冲区和 Channel 通道来处理数据的。可以简单理解为把Channel通道比作 铁路,buffer缓冲区比作成火车(运载着货物),而NIO就是通过来实现数据的处理。Buffer 是缓冲区的抽象类,ByteBuffer 是(在通道中读写字节数据):拿到一个缓冲区我们往往会做什么?很简单,就是。所以,缓冲区的核心方法就是 put 和 get:Buffer 类维护了 4 个核心变量来提供。get()put()现在,怎么拿呀。

qq_62636650的博客 1564

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

java笔记--NIO基础--Buffer缓冲区

注意,执行完写操作后想要进行读之前,要执行filp()方法翻转:limit = position;| 使用 | put/get/channel 读写 | 不走 JVM 堆,效率高 || 释放 | 依赖 GC 和 Cleaner | 不可手动释放,不能频繁创建 || native 分配堆外内存 |

lxq6966892的博客 1246

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java NIO之缓冲区Buffer分析

目录 Buffer介绍 ByteBuffer介绍 ByteBuffer案例 总结 Buffer介绍 1.Buffer简介       缓冲区(Buffer)是中NIO中基础的内容,存在于包java.nio下面.一个Buffer对象可以看做是一个存储数据的容器,数据被存储到这里后可以进行检索。缓冲区工作与通道关联,我们不与通道直接进行交互,而是通过缓冲区将数据传送到通道里,或者从通道获...

梦悠哉的博客 1740

Java NIO ———— Buffer 缓冲区详解

引言 缓冲区是一个用于特定基本类型的容器。由java.nio 包定义,所有缓冲区都是 Buffer 抽象类的子类。 Java NIO 中的 Buffer ,主要用于与NIO 通道进行交互。数据从通道存入缓冲区,从缓冲区取出到通道中。 一、创建缓冲区 缓冲区的本质是数组,用于存储不同类型的数据,根据数据类型(boolean 除外),提供了相应类型的缓冲区,如ByteBuffer、In...

Morty的技术乐园 2450

Java NIO——缓冲区Buffer

目录什么是Java NIO 什么是Java NIO Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。 Java NIO系统的核心在于:通道(Channel)和缓冲区(Buffer)。通道表示打开到 IO 设备(例如:文件、套接字)的连接。若需要使用 NIO 系统,需要获取用于连接 I

guochaoHNU的博客 1127

《Java源码解析》NIO中Buffer缓冲区的实现

Buffer 缓冲区Java的NIO中Buffer至关重要:buffer是读写的中介,主要和NIO的通道交互。数据是通过通道读入缓冲区和从缓冲区写入通道的。其实缓冲区buffer的本质就是一块可以读写的内存块。这块内存块被包装成NIO的Buffer对象,并提供了一组方法方便读写。3.1 Buffer的基本用法:使用Buffer读写数据一般是下面步骤: 1. 写入数据到Buffer 2. 调用fl

惜暮 2480

JAVA NIO(二)NIO之缓冲区(Buffer)详解

缓冲区在java NIO中负责数据的存取。缓冲区就是数组,用于存储不同数据类型的数据

zjx2016的博客 775

Java-NIO之Buffer(缓冲区)

Buffer 是什么 Buffer(缓冲区)本质上是一个由基本类型数组构成的容器。 我们先看看Buffer类的基本构成: public abstract class Buffer { // Invariants: mark <= position <= limit <= capacity private int mark = -1; private int position = 0; private int limit; private in

HongYu012的博客 1038

Java NIO三大核心之缓冲区Buffer概述

定义 缓冲区Buffer在java nio中负责数据的存储,缓冲区就是数组,用于存储不同类型数据的数组。 jdk为java七大基本类型数据都准备了响应的缓冲区(boolean值除外): ByteBuffer CharBuffer ShortBuffer IntegerBuffer LongBuffer FloatBuffer DoubleBuffer 上述缓冲区除了ByteBuffer的 功能稍微多点外,因为ByteBuffer是通用的,所以功能会比较多。其他6种的使用方式几乎是一致的。 /* * B

lixinkuan的博客 3770

Java NIO之缓冲区Buffer

NIO与IO的区别 由面向存取数据的载体、是否阻塞等可以分为以下三点不同: 面向流: 数据像水流一样传输,并且,要么输入要么输出,流是单向的。所以以前的IO流都有输入流,输出流。 面向缓冲区: NIO会在程序与文件(磁盘、网络)之间建立一个通道用于连接,然后通过缓冲区进行数据存取,通过通道进行连接传递。 阻塞IO和非阻塞IO、选择器主要是针对网络编程而言的。 通道( Ch...

ystyaoshengting的专栏 589

Java NIO系列3:缓冲区

前言一直想把NIO系列的文章更新下去,只不过发现在入职支付宝后工作实在是忙,所以一直拖到现在。直接从一个学生过狗成为一名加班狗,好吧,这就是互联网公司的现状吧,但是每天都是充实的,而且发现其他的员工也基本非常乐意加班,难道这就是阿里的文化熏陶?!废话不多说,还是进入今天的正题,在前面的文章中,我们已经对Java的NIO有了一个粗浅的认识——主要之为了支持非阻塞I/O的操作,之前的BIO则是阻塞的。因

rhwayfun专栏 5620

NIO学习笔记——缓冲区(Buffer)详解

缓冲区是包在一个对象内的基本数据元素数组,Buffer类相比一个简单的数组的优点是它将关于数据的数据内容和信息包含在一个单一的对象中。Buffer的属性容量(capacity):缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变 上界(limit):缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数 位置(position):下一个要被读或写的元素

路漫漫,水迢迢 8463
上一篇: Java NIO笔记(一):NIO介绍
下一篇: Java NIO笔记(三):NIO Buffer(缓冲区)之进阶
xlight2023
博客等级 码龄15年 236粉丝 32原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值