一文解读java.nio.ByteBuffer
作者:bjxiaxueliang
java.nio.ByteBuffer
是一个可以进行 缓冲区分配 、 读取 和 写入 的缓冲区,其 持有一个字节数组
并通过4个属性:
capacity
limit
position
mark
来管理缓冲区,进行字节级别读取和数据写入。
基于此,ByteBuffer常被用来处理网络协议和I/O操作。
一、使用举例
以下为ByteBuffer的使用举例:
- 可以使用
put()
方法将数据写入缓冲区; - 可以使用
flip()
方法切换缓冲区为读取模式; - 可以使用
rewind()
方法倒回缓冲区的初始位置; - 可以使用
get()
方法读取缓冲区中的数据; - 可以使用
clear()
方法清空缓冲区,以便再次写入数据。
import java.nio.ByteBuffer; public class JavaTest { public static void main(String[] args) { System.out.println("~~~~~~~~ put(byte b) ~~~~~~~~"); // 分配一个5字节的buffer ByteBuffer byteBuffer = ByteBuffer.allocate(5); // 向buffer中添加两个字节的数据,空余3个字节数据 byteBuffer.put((byte)10); byteBuffer.put((byte)20); // 输出整个字节数组 printByteBuffer(byteBuffer); System.out.println("~~~~~~~~ flip() ~~~~~~~~"); // 转为读模式 byteBuffer.flip(); // 输出整个字节数组 printByteBuffer(byteBuffer); System.out.println("~~~~~~~~ get() ~~~~~~~~"); // 读取当前 position System.out.println(byteBuffer.get()); // 输出整个字节数组 printByteBuffer(byteBuffer); System.out.println("~~~~~~~~ rewind() ~~~~~~~~"); // 倒回缓冲区的初始位置 byteBuffer.rewind(); printByteBuffer(byteBuffer); System.out.println("~~~~~~~~ get(byte[] dst, int offset, int length) ~~~~~~~~"); // 将buffer中数据写入到dstBytes中 byte[] dstBytes = new byte[2]; byteBuffer.get(dstBytes, 0, dstBytes.length); printByteBuffer(byteBuffer); } public static void printByteBuffer(ByteBuffer byteBuffer) { byte[] bytes = byteBuffer.array(); int position = byteBuffer.position(); int limit = byteBuffer.limit(); int remining = byteBuffer.remaining(); System.out.println("byteBuffer: " + Arrays.toString(bytes) + "\nPosition: " + position + " Limit: " + limit + " Remining: " + remining); } }
控制台输出如下:
~~~~~~~~ put(byte b) ~~~~~~~~
byteBuffer: [10, 20, 0, 0, 0]
Position: 2 Limit: 5 Remining: 3
~~~~~~~~ flip() ~~~~~~~~
byteBuffer: [10, 20, 0, 0, 0]
Position: 0 Limit: 2 Remining: 2
~~~~~~~~ get() ~~~~~~~~
10
byteBuffer: [10, 20, 0, 0, 0]
Position: 1 Limit: 2 Remining: 1
~~~~~~~~ rewind() ~~~~~~~~
byteBuffer: [10, 20, 0, 0, 0]
Position: 0 Limit: 2 Remining: 2
~~~~~~~~ get(byte[] dst, int offset, int length) ~~~~~~~~
byteBuffer: [10, 20, 0, 0, 0]
Position: 2 Limit: 2 Remining: 0
二、原理简析
前边说过 ByteBuffer持有一个字节数组
并通过4个属性:
capacity
limit
position
mark
来管理缓冲区
这4个属性遵循
mark <= position <= limit <= capacity
下表格是对着4个属性的解释:
属性 | 描述 |
---|---|
Capacity | 容量,即可以容纳的最大数据量 |
Limit | 缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作 |
Position | 下一个要被读或写的元素的索引 |
Mark | 标记。可调用mark()设置标记(mark=position),然后调用reset()让position恢复到标记的位置 |
初始化,各控制属性状态:
例如调用
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
进行ByteBuffer存储空间分配,
各属性见下图所示:
写入数据后,各控制控制属性状态:
例如调用
byteBuffer.put((byte)'a')
写入数据后,
各属性见下图所示:
读取数据后,各控制控制属性状态:
例如调用
byteBuffer.get()
读取4个字节后,
各属性见下图所示:
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。