这是我参与更文挑战的第25天,活动详情查看:更文挑战
一、前言
Buffer 可当作成缓冲区,或中转站,如图:
磁盘数据先经过
Buffer,再到内存。缓冲区(
Buffer) :就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区。
一个Buffer对象是固定数量的数据的容器。
其属性有:
- 容量(
Capacity): 缓冲区能够容纳的数据元素的最大数量。 - 上界(
Limit): 缓冲区的第一个不能被读或写的元素, 用于计数。 - 位置(
Position): 下一个要被读或写的元素的索引。 - 标记(
Mark): 一个备忘位置; 当调用reset()方法,position会回到mark指向的位置。
读写模式下, capacity、limit、position
二、API 使用
使用Buffer读写数据基本步骤:
- 写入数据到
Buffer - 调用
flip()方法 - 从
Buffer中读取数据 - 调用
clear()方法或者compact()方法
ByteBuffer buf = ByteBuffer.allocate(1024);
// 从 channel 中读取
int bytesRead = inChannel.read(buf);
while(bytesRead != -1) {
buf.flip();
while(buf.hasRemaining()) {
System.out.println((char) buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
(1) Buffer 分配、读、写
directBuffer 与 buffer 区别,如图:
// 从磁盘文件 / 网络里 读取数据
ByteBuffer buf = ByteBuffer.allocate(1024);
ByteBuffer directBuf = ByteBuffer.allocateDirect(1024);
// 如果用 direct 模式,整体性能会比普通模式高一些。
如下 demo 演示 buffer 分配、读取、写入操作:
// 1. 分配 Buffer
ByteBuffer buffer = ByteBuffer.allocateDirect(100);
System.out.println("capacity : " + buffer.capacity());
System.out.println("position : " + buffer.position());
System.out.println("limit : " + buffer.limit());
byte[] src = new byte[] {1, 2, 3, 4, 5};
// 2. 放置数据,移动 position
buffer.put(src);
// position = 0~4,都填充了数据
System.out.println("position : " + buffer.position());
// 此时 position = 5,此时如果你直接读数据,是读不到的,是空的没有数据。
// 手动操作一下 position,调整到 position = 0的地方,开始读数据
buffer.position(0);
byte[] dst = new byte[5];
// 3. 将数据写到目标数组中
buffer.get(dst);
System.out.println("position : " + buffer.position());
输出如下:
capacity : 100
position : 0
limit : 100
position : 5
position : 5
dst=[0,1,2,3,4]
(2)通常调用 Buffer API 操作缓冲区
clear()方法
Buffer被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。
position将被设回0,limit被设置成 capacity的值。
flip()方法
将
Buffer从 写模式 切换到 读模式
即将position设置为0, 并将limit设置成之前的position。
rewind()方法
将
position设置为0,并且丢弃mark。一般先读取了一遍数据,接着想要再次重新读取一遍数据,这个时候可以用
rewind,此时limit是不变的。