Skip to content

Buffer基础

1. Buffer简介

Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。 Alt text 缓冲区本质上是一块可以读写数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。Buffer底层就是一个数组,在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问NIO中的数据,都是将它放到缓冲区中。而在面向流I/O系统中,所有数据都是直接写入或者直接将数据读取到Stream对象中。 在NIO中,所有的缓冲区类型都继承于抽象类Buffer,最常用的就是ByteBuffer,对于Java中的基本类型,基本都有一个具体Buffer类型与之相对应,它们之间的继承关系如下图所示:
Alt text

2. 读写模式原理

为了记录读写的状态和位置,Buffer类提供三个重要的属性:capacity(容量)、position(读写位置)和limit(读写的限制)。
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的,表示buffer的大小容量。需要注意的是一旦Buffer初始化,就不能再改变capacity。 下图为Buffer的初始状态:
Alt text

2.1 Buffer写模式

  • position表示写入数据的当前位置,position的初始值为0,position最大可为capacity–1。
  • limit表示可对Buffer最多可以写入多少数据。limit最大等于capacity。

下图表示写入了4个字节后的状态:
Alt text

2.2 Buffer读模式

  • position为0,最大值为limit。
  • limit表示Buffer里有多少可读数据量。

flip()发生后,position切换为读取位置,limit切换为读取限制 Alt text

2.3 Buffer模式切换

flip()方法`clear()方法\compact()`方法都会导致Buffer模式切换:

  • 执行flip()方法如上读模式。
  • 执行clear()方法后,如下图可以看到Buffer回到初始状态,也就是写状态:
    Alt text
  • 执行compact()方法,是把未读完的部分向前压缩,然后切换至写模式:
    Alt text

3. Buffer读写操作

3.1 使用Buffer写数据

写数据到Buffer有两种方式:

  • 从Channel写到Buffer
  • 通过Buffer的put()方法写到Buffer里
java
// 从通道里面读数据到Buffer里面
int bytesRead = inChannel.read(buf); 
// 通过 put 方法写 Buffer
buf.put(127);

3.2 读数据

从Buffer中读取数据有两种方式:

  • 从Buffer读取数据到Channel。
  • 使用get()方法从Buffer中读取数据。
java
//从 Buffer 读取数据到 Channel
int bytesWritten = inChannel.write(buf);
// 使用get()方法从Buffer中读取数据
byte aByte = buf.get();
// 读取位置1数据
buffer.get(1);
// 读取多个位置数据
int[] posArray = {3,6,7};
IntBuffer subBuffer = buffer.get(posArray);