Buffer
Buffer是什么
它用来传输数据,应用于操作系统,是面向缓冲区的,非阻塞;
Buffer 缓冲区实际上就是一个数组, 把数组的内容与信息包装成一个 Buffer 对象,提供访问这些信息的方法;
Buffer常识
Buffer中有ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer, IntBuffer,LongBuffer,ShortBuffer,实际上使用较多的是 ByteBufer, CharBuffer;
Buffer用capacity、position、limit、mark属性用来对缓冲区读取信息进行标识;
capacity:创建Buffer时,缓冲区能存储多少数据,创建后不能修改可以清空继续写数据;
position:初始化为0,最大值为capacity-1,切换到读模式position会初始化为0;
limit:是指第一个不能被读出或写入的位置;
mark:设置的标记位置,使用mark方法对当前位置进行标记,使用reset方法将位置放到标志位置;
0 <= mark <= position <= limit <= capacity
切记切换成读模式后原来的positon会变成读模式的limit
直接字节缓冲区:缓冲区中只有ByteBuffer能够参与IO操作,直接字节缓冲区通常是 I/O 操作最好的选择,如果使用非直接字节缓冲区可能会导致性能损耗;
Buffer常用API
CharBuffer.allocate(int) 声明非直接缓冲区参数代表缓冲区大小
capacity() 方法返回缓冲区的大小
hasRemaining() 判断当前 position 后面是否还有可处理的数据,即判断postion与limit之间是否还有数据可处理
limt() 返回 limit 上限的位置
mark() 设置缓冲区的标志位置, 这个值只能在 0~position 之间。 以后可以通过 reset()返回到这个位置
position() 可以返回 position 当前位置
remainig() 返回当前 position 位置与 limit 之间的数据量
reset() 方法可以将 position 设置为 mark 标志位
rewind() 将 position 设置为 0, 取消 mark 标志位
clear() 清空缓冲区,仅仅是修改 position 标志为 0, 设置 limit 为 capacity, 缓冲区中数据还是存在的
flip() 方法可以把缓冲区由写模式切换到读模式。 先把 limit 设置为 position 位置,再把position 设置为 0
compact() 把 buffer 中未读的数据复制到 position 为 0 的位置
ByteBuffer.allocateDirect();方法创建直接字节缓冲区
简单使用
使用CharBuffer进行简单读写
package com.lizhiyu.com;
import java.nio.CharBuffer;
public class Test {
public static void main(String[] args) {
//创建缓冲区
CharBuffer buffer=CharBuffer.allocate(100);
buffer.put('1');
buffer.put('2');
buffer.put('3');
buffer.put('4');
buffer.put('5');
System.out.println(
"capacity:" + buffer.capacity() +
",limit:" + buffer.limit() +
",position:" + buffer.position());
//切换成读模式,position设置成0,数据不变
buffer.flip();
//通过循环把 position 与 limit 之间的内容逐个打印
while(buffer.hasRemaining()){
//获得数据后position+1
System.out.println(buffer.get());
}
//仅仅是清空limit和position的值,不对数据进行清空
buffer.clear();
System.out.println(
"capacity:" + buffer.capacity() +
",limit:" + buffer.limit() +
",position:" + buffer.position());
//当切换为读模式的时候position 的位置变为limit为存储数据的数量
//之前调用了clear方法,limit为之前的position位置
//之前调用了clear方法limit变成了capacity所以打印除了所有数据
System.out.println(buffer);
while(buffer.hasRemaining()){
//获得数据后position+1
System.out.println(buffer.get());
}
}
}
使用数组进行创建CharBuffer,批量读取CharBuffer
package com.lizhiyu.com;
import java.nio.CharBuffer;
public class Test {
public static void main(String[] args) {
char[] charArray={'1','2','3','4','5','6','7','8','9','a'};
//通过CharBuffer.wrap方法将charArray中的数据创建一个缓冲区
CharBuffer charBuffer = CharBuffer.wrap(charArray);
charBuffer.get();
char[] charArray2=new char[10];
//将缓冲区的数据从position开始到limit 放到charArray2数组中
//charBuffer.remaining()代表position和limit中相差多少
CharBuffer charBuffer2 = charBuffer.get(charArray2, 0, charBuffer.remaining());
charBuffer2.flip();
System.out.println(charBuffer2);
//将数据批量写入缓冲区
CharBuffer charBuffer3=CharBuffer.allocate(10);
charBuffer3.put(charArray,0,charBuffer3.remaining());
charBuffer3.flip();
System.out.println(charBuffer3);
}
}
缓冲区的复制与分隔,CharBuffer随着其绑定数组改变而改变
package com.lizhiyu.com;
import java.nio.CharBuffer;
public class Test {
public static void main(String[] args) {
//通过put往缓冲区中批量添加数据
CharBuffer charBuffer=CharBuffer.allocate(16);
charBuffer.put("1234567890");
charBuffer.flip();
System.out.println(charBuffer);
char[] charArray= {'1','2','3','4','5'};
//通过数组创建缓冲区,数组中的数据改变缓冲区中的数据跟着改变
CharBuffer charBuffer2 = CharBuffer.wrap(charArray);
System.out.println(charBuffer2);
charBuffer2.get();
//缓冲区的复制
//使用duplicate进行复制出来的buffer底层引用同一个数组
//将position也会进行复制
CharBuffer duplicate = charBuffer2.duplicate();
System.out.println(duplicate);
//设置位置
duplicate.position(3);
//将缓冲区进行分割
//创建一个新的缓冲区数据为原来缓冲区的[position,limit)
CharBuffer sliceBuffer = duplicate.slice();
System.out.println(sliceBuffer);
}
}
缓冲区IO操作
使用ByteBuffer联合Channel进行读取文件
其中使用直接字节流缓冲区性能更高,读取文件速度可能会更快
//非直接字节流缓冲区
ByteBuffer byteBuffer=ByteBuffer.allocate(100);
//直接字节流缓冲区
ByteBuffer allocateDirect = ByteBuffer.allocateDirect(100);