ByteBuffer正确使用了向buffer写入数据的步骤,比如调用intn=channel.read(buffer);如果返回值n=-1,则表示读取完成。调用flip()切换到读取模式,从buffer中读取数据,例如调用buffer.get();调用clear()或compact()切换到写入模式,重复1~4步。ByteBuffer源码ByteBuffer主要参数://Invariants:mark<=position<=limit<=capacityprivateintmark=-1;//当调用mark()方法时,position会被赋值给markprivateintposition=0;//表示下一个要读或写的位置privateintlimit;//表示第一个不可读不可写元素的位置privateintcapacity;//ByteBuffer,表示可以容纳的元素个数ByteBuffer有两个构造函数,都是protected。所以我们不能使用新方法来构造对象//使用给定的标记、位置、限制、容量、//支持数组和数组偏移量创建一个新缓冲区//ByteBuffer(intmark,intpos,intlim,intcap,//package-privatebyte[]hb,intoffset){super(mark,pos,lim,cap);这个.hb=hb;this.offset=offset;}//使用给定的标记、位置、限制和容量创建一个新缓冲区//ByteBuffer(intmark,intpos,intlim,intcap){//package-privatethis(mark,pos,lim,cap,null,0);}我们可以使用allocate()和allocateDirect()构造ByteBufferpublicstaticByteBufferallocateDirect(intcapacity){returnnewDirectByteBuffer(capacity);}publicstaticByteBufferallocate(intcapacity){if(capacity<0)throwcreateCapacityException(capacity);}returnnewHeapByteBuffer(capacity);}内部原理通过allocate()或allocateDirect()构造一个newByteBuffer后positionon=0;标记=-1;限制=容量;当前模式为写入模式时:position为下一个要写入的位置。使用时切换读写模式当flip()切换到读取模式时:limit设置为下一个要写入的字节的位置,position为下一个要读取的字节的位置,每次读取后都是position++;读取时如果位置超过限制,会抛出BufferUnderflowExceptionpublicBufferflip(){limit=position;位置=0;标记=-1;returnthis;}使用clear()切换到读模式时:回到初始状态,下一个写入字节的位置为0这个方法相当于清空ByteBuffer的所有状态publicBufferclear(){position=0;限制=容量;标记=-1;returnthis;}也可以使用compact()方法切换到读取模式,相对于clear()方法,该方法会保留上次未读取的字节,将其复制到内部字节数组的最前面,并且然后使位置成为未读字节的长度。重要方法get()get()方法会让位置读指针往回走。如果要重复读取数据,调用rewind()方法将位置重置为0。调用get(inti)方法获取索引i的内容,它不会移动读指针rewind()并将position设置为0,相当于从头读取publicBufferrewind(){position=0;标记=-1;returnthis;}mark()&reset()注:rewind()和flip()会清除mark位置,将当前读写位置赋给mark做mark,可以恢复到mark位置通过reset()方法。publicBuffermark(){标记=位置;returnthis;}改变当前位置为上次保留的读写位置,设置位置为markpublicBufferreset(){intm=mark;如果(m<0)抛出新的InvalidMarkException();位置=米;returnthis;}characterbyteconversionstringconversionForbytes://String直接转为字节数组ByteBufferbuffer1=ByteBuffer.allocate(16);buffer1.put("hello".getBytes());//CharsetByteBufferbuffer2=StandardCharsets.UTF_8.encode("hello");//warpByteBufferbuffer3=ByteBuffer.wrap("hello".getBytes());将字节转换为字符://ByteBuffer到StringStrings=StandardCharsets.UTF_8.decode(buffer2).toString();System.out.println(s);文本文件为一个时的分散读集中写ree的时候,我们可以一次性读取一个很大的ByteBuffer,然后再划分,这样会造成效率低下。我们可以采用分散读取,读入相应长度的ByteBuffer,然后进行后续处理分配(3);ByteBufferb2=ByteBuffer.allocate(3);ByteBufferb3=ByteBuffer.allocate(5);//分别读入对应长度的ByteBufferchannel.read(newByteBuffer[]{b1,b2,b3});b1.翻转();b2.翻转();b3.翻转();System.out.println(b1);//一个System.out.println(b2);//两个System.out.println(b3);//三}catch(IOExceptione){e.printStackTrace();}当我们需要把一批数据写入文件,可以单独写入,会造成IO效率低,可以集中写入,聚集在一起,一次性写入文件ByteBufferb1=StandardCharsets.UTF_8.encode("你好");//5字节ByteBufferb2=StandardCharsets.UTF_8.encode("world");//5字节ByteBufferb3=StandardCharsets.UTF_8.encode("Hello");//6字节尝试(FileChannelchannel=newRandomAccessFile("GatheringWrites.txt","rw").getChannel();){channel.write(newByteBuffer[]{b1,b2,b3});}catch(IOExceptione){e.printStackTrace();}
