Java NIO之ByteBuffer的介绍和使用

简介: 笔记
  • ByteBuffer类位于java.nio包下,所谓nio:代表new io,另一种解释:N代表Non-blocking IO,非阻塞的IO

Buffer是一个抽象的基类


派生类:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer

Buffer的几个基本属性


  • 基础属性,使用ByteBuffer是以字节Byte为基础的,操作对象是字节
  • capacity--Buffer的容量,读取数据的限制和读取数据的位置,capacity 是分配好的一个内存块大小,分配好后大小不可变
  • limit--在读的模式下,表示缓存内数据的多少,limit<=capacity; 在写的模式下,表示最多能存入多少数据,此时limit=capacity;简单说:在Buffer上进行的读写操作都不能越过这个下标。
  • position--表示读写的位置,下标从0开始


Buffer的几个方法


  • clear()--position置为0,limit转为capacity大小,标记mark也会被清除
  • flip()--limit被置为当前position的大小,也就是说后续的读操作可能会被限制,这是与clear()有区别的地方;然后position被置为0
  • rewind()--position置为0,标记被取消


使用举例


基本用法

ByteBuffer byteBuffer = ByteBuffer.allocate(10);//分配10个字节大小的缓存 
byteBuffer.putInt(5);//int占用4个字节
byteBuffer.put((byte) 1);//1个字节
byteBuffer.put((byte) 0);//1个字节
byteBuffer.put("abc".getBytes());//2个字节
System.out.printf("position: %d, limit: %d, capacity: %d\n", buf.position(), buf.limit(), buf.capacity());

打印结果:

position: 9, limit: 10, capacity: 10

分析:byteBuffer刚开始分配了10个字节的缓存,放入一个Int值5,占用4个字节,两个byte数又占两个,adb占用三个字节,总共占用了9个字节。从打印结果中看到,position为9表示已经存储了9个字节即下标0-8,limit表示在写模式下最多存储10个字节,capacity为10表示缓存容量为10。

java.nio.BufferOverflowException

因为ByteBuffer的大小不可变的,所以如果存储的长度超过capacity,那么就会抛出java.nio.BufferOverflowException异常,表示缓冲区上溢出,写入的位置超出了内存长度。


flip()和clear()

flip方法的作用是先将limit属性设置为当前的position的值,再将position转为0,并清除标记。

clear方法的不同之处是limit=capacity。

ByteBuffer byteBuffer = ByteBuffer.allocate(10);
byteBuffer.putInt(5);//int占用4个字节
byteBuffer.put((byte) 1);
byteBuffer.put((byte) 0);
byteBuffer.put("abcd".getBytes());
printByteBuffer(byteBuffer);
// 读取消息头,因为写完后position已经到10了,所以需要先反转为0,再从头读取
byteBuffer.flip();//将position置0
//需要按顺序读取,position自增
System.out.printf("读取int值: %d\n", byteBuffer.getInt());//读int
System.out.printf("读取byte值: %d\n", byteBuffer.get());//读byte
System.out.printf("读取byte值: %d\n", byteBuffer.get());//读byte
byte[] str = new byte[4];
byteBuffer.get(str, 0, 4);//连续读4个字节,并保存到str中,注意第二个参数是相对于position的偏移量
System.out.println("读取字符串=" + new String(str));

打印结果如下:

position: 10, limit: 10, capacity: 10
读取int值: 5
读取byte值: 1
读取byte值: 0
读取字符串=abcd

java.nio.BufferUnderflowException

试一下flip()的使用。上面介绍中提到,flip()的作用是先将limit属性设置为当前的position的值,再将position转为0。也就是说如果当前的position是小于实际保存的字节长度的,那么下次就最多读取到这个position的位置,如果超出则会抛出异常。

ByteBuffer byteBuffer = ByteBuffer.allocate(10);
byteBuffer.putInt(5);//int占用4个字节
byteBuffer.put((byte) 1);
byteBuffer.put((byte) 0);
byteBuffer.put("abcd".getBytes());  
byteBuffer.clear();
//先读取一个int,再flip()
System.out.printf("读取int值: %d\n", byteBuffer.getInt());//读int
byteBuffer.flip();
System.out.printf("position: %d, limit: %d, capacity: %d\n", byteBuffer.position(), byteBuffer.limit(), byteBuffer.capacity());
//需要按顺序读取,position自增
System.out.printf("读取int值: %d\n", byteBuffer.getInt());//读int
System.out.printf("读取byte值: %d\n", byteBuffer.get());//读byte
System.out.printf("读取byte值: %d\n", byteBuffer.get());//读byte

打印结果:

读取int值: 5
position: 0, limit: 4, capacity: 10
读取int值: 5
java.nio.BufferUnderflowException
    at java.nio.Buffer.nextGetIndex(Buffer.java:500)
    at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:135)
    at com.heima.ajax.JacksonTest.testByteBuffer(JacksonTest.java:83)

此时报出了内存下溢出的异常,说明读取的位置超出了限制。

目录
相关文章
|
2月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
1月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
28 2
|
19天前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
42 0
|
27天前
|
存储 网络协议 Java
【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!
【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。
43 0
|
2月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
119 1
|
29天前
|
存储 Java
如何在 Java 中写入和读取 ByteBuffer
【8月更文挑战第22天】
50 0
|
29天前
|
存储 Java
如何在 Java 中创建 ByteBuffer
【8月更文挑战第22天】
32 0
|
2月前
|
安全 Java
【Java】已解决java.nio.channels.OverlappingFileLockException异常
【Java】已解决java.nio.channels.OverlappingFileLockException异常
65 1
|
2月前
|
Java
【Java】已解决java.nio.channels.ClosedChannelException异常
【Java】已解决java.nio.channels.ClosedChannelException异常
191 1
|
2月前
|
Java
【Java】已解决java.nio.channels.FileLockInterruptionException异常
【Java】已解决java.nio.channels.FileLockInterruptionException异常
23 1