志宇-NIO之Buffer

mac2026-05-24  3

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);
最新回复(0)