JAVA NIO之Buffer
Buffer就是一个数据存储器。数据可以存储在其中并在之后用于检索。
在Buffer的源码中可以看到:
// Invariants: mark <= position <= limit <= capacity private int mark = - 1 ; private int position = 0 ; private int limit; private int capacity; |
这四个就是缓冲区的重要属性。
容量(Capacity):缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。
上界(Limit):缓冲区的第一个不能被读或写的元素。或者说,limit后既不可读也不可写。
位置(Position):下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。
标记(Mark):一个备忘位置。调用 mark( )来设定 mark = postion。调用 reset( )设定 position =mark。标记在设定前是未定义的(undefined)。
Buffer类的api方法:
除了boolean其他基本类型都有相应的buffer。常用的为CharBuffer、ByteBuffer。下面是一个简化的类图。
下面我们就来实际操作buffer,以CharBuffer为例。
1.创建一个CharBuffer
CharBuffer charBuffer = CharBuffer.allocate( 10 ); System.out.println( "容量capacity=" +charBuffer.capacity()+ " 界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); |
输出:容量capacity=10 界限limit=10 位置position=0,关系如下如图
2.向上面的buffer添加四个元素。
charBuffer.put( "q" ); charBuffer.put( "w" ); charBuffer.put( "e" ); charBuffer.put( "r" ); //加入四个元素 输出:界限limit=10 位置position=4 System.out.println( "加入四个元素 界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); |
输出:加入四个元素 界限limit=10 位置position=4,关系如下图
3.调用flip()方法,Buffer从写模式切换到读模式,将limit设置为position,position设为0。
charBuffer.flip(); //输出:界限limit=4 位置position=0 System.out.println( "flip()后:界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); |
输出:flip()后 :界限limit=4 位置position=0,关系如下图
4.此时buffer为可读,我们从中读取数据。
//取出第一个元素 System.out.println( "相对取出一个元素get():" +charBuffer.get()); //界限limit=4 位置position=1 System.out.println( "相对取出一个元素get()后: 界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); |
输出:相对取出一个元素get()后: 界限limit=4 位置position=1,关系如下图。
5.调用clear()让buffer回到写模式,clear()将limit变为capacity,position=0,上面添加的数据依然存在buffer中。
//clear()将limit变为capacity,position=0,数据依然存在 charBuffer.clear(); //界限limit=10 位置position=0 System.out.println( "clear()后:界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); |
输出:clear()后:界限limit=10 位置position=0,关系如下图,和初始时相似,但现在buffer里有数据。
6.根据索引绝对访问get(x),取值不会影响position
//get(3)根据索引取值不会影响position System.out.println( "根据索引绝对访问get(1)=" +charBuffer.get( 3 )); System.out.println( "根据索引绝对访问get(1)后: 界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); |
输出:根据索引绝对访问get(1)=r;根据索引绝对访问get(1)后: 界限limit=10 位置position=0
7.buffer的释放。释放有两种方式:
a.)
CharBuffer buffer1 = CharBuffer.allocate( 8 ); buffer1.put( "a" ); buffer1.put( "b" ); buffer1.put( "c" ); buffer1.flip(); //释放1,布尔函数 hasRemaining()会在释放缓冲区时判断是否已经达到缓冲区的上界 char [] receive1 = new char [ 32 ]; for ( int i = 0 ;buffer1.hasRemaining();i++){ receive1[i] =buffer1.get(); System.out.println( "释放1 hasRemaining:receive[" +i+ "]=" +receive1[i]); } |
b.)
CharBuffer buffer2 = CharBuffer.allocate( 8 ); buffer2.put( "1" ); buffer2.put( "2" ); buffer2.put( "3" ); buffer2.flip(); //释放2,remaining()函数:从当前位置到上界还剩余的元素数目 int count = buffer2.remaining(); char [] receive2 = new char [ 32 ]; for ( int i= 0 ;i<count;i++){ receive2[i] =buffer2.get(); System.out.println( "释放2 remaining:receive[" +i+ "]=" +receive2[i]); } |
8.批量移动,上面说的方式移动数据效率不高,NIO的buffer还提供了更加高效的方式。
package com.nio.java; import java.nio.CharBuffer; /** * 批量移动数据 * @author monkjavaer * @date 2018/10/16 15:29 */ public class BufferTest2 { public static void main(String[] args) { CharBuffer charBuffer = CharBuffer.allocate( 10 ); System.out.println( "容量capacity=" +charBuffer.capacity()+ " 界限limit=" +charBuffer.limit()+ " 位置position=" +charBuffer.position()); charBuffer.put( "q" ); charBuffer.put( "w" ); charBuffer.put( "e" ); charBuffer.put( "r" ); charBuffer.put( "t" ); charBuffer.flip(); ////buffer.get(smallArray);等价于:buffer.get(smallArray,0,smallArray.length); //如果数组比较小不能装下待处理的数据,就需要指定长度,否则buffer.get(smallArray)会抛出java.nio.BufferUnderflowException char [] smallArray = new char [ 2 ]; while (charBuffer.hasRemaining( )) { int length = Math.min (charBuffer.remaining( ), smallArray.length); System.out.println( "length=" +length); charBuffer.get (smallArray, 0 , length); processData(smallArray,length); } } /** * 处理数据 * @param smallArray * @param length 数组中有多少待处理数据 */ public static void processData( char [] smallArray, int length){ System.out.println( "===processData====" ); for ( int j = 0 ;j<length;j++) { System.out.println( "smallArray[" +j+ "]=" +smallArray[j]); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步