byteBuffer几个方法含义: java
三者关系:函数
标志位 | 初始值 | 说明 |
---|---|---|
mark | -1 | 标记位 |
position | 0 | 当前位置 |
limit | 指定的缓冲区容量 | 已写入有效数据容量 |
capacity | 指定的缓冲区容量 | 缓冲区容量 |
ByteBuffer提供两种不一样的构造函数,其本质主要是构建的ByteBuffer类型不一样,其中一种构造函数参照源代码:性能
//第一种,分配的是DirectByteBuffer public static ByteBuffer allocateDirect(int capacity) { return new DirectByteBuffer(capacity); } //第二种,分配的是HeapByteBuffer public static ByteBuffer allocate(int capacity) { if (capacity < 0) throw new IllegalArgumentException(); return new HeapByteBuffer(capacity, capacity); }
详细两种不一样类型的Buffer这里不展开讨论,可是大多数状况下,若是对性能没有太大要求的话,通常默认使用HeapByteBuffer。当咱们执行初始化操做后: ByteBuffer.allocate(缓冲区大小);
. this
其中初始化的值,分别为position=0,limit和capacity等于咱们指定的缓冲区大小,mark默认为-1。网上有一些教程的图示默认显示了mark为起始点,实际上是一种低级错误,让别人误觉得mark就等于起始位置。spa
顾名思义,put操做就是就是将数据放入缓冲区中,每一次put操做,都会position加上put进去的数据长度.position每加一,表明缓冲区内增长了一个字节的数据,具体put的操做原理以下: code
若是送入的数据大小大于缓冲区剩余容量,则会抛出异常:java.nio.BufferOverflowException
,虽然可能有实际部分数据被写入缓冲区,可是flip以后,limit位置仍是最后一次正确写入缓冲区的位置。教程
Flip,回针(请联想老式打字机),是让limit指向当前position的位置,position指向起始位置,此时position=0,进行这一部操做以后,就能够肯定了当前缓冲区的有效数据。而且为数据读取作准备。ip
Get操做,就是按照position当前位置,取出缓冲区的数据,每一次取操做以后,position都会get出的数据长度。一样,position每加一,表明从缓冲区内读取到了一个字节的数据,不过数据并不会被删除,只是单纯的读取操做。若是,get以后,position值大于limit值,则抛出异常:java.nio.BufferUnderflowException
ci
mark,就是标记当前的位置,一旦后续进行reset操做以后,能够快速地定位到mark的位置。在某一些应用场合中,配合reset,这是一个很是方便的操做函数。get
一旦进行过mark操做以后,后续读取操做中,若是再执行reset操做,就能够快速定位到标记位上:
Clear操做很简单,就是全部标志位都会被恢复成默认值,包括mark值,可是记住,不是数据,写入缓冲区的数据仍然保留,若是这时候执行get操做,仍然能够将数据获取出来。直观的话,能够直接看源代码:
public final Buffer clear() { position = 0; limit = capacity; mark = -1; return this; }
slice方法的做用,就是作数据分割,将当前的position到limit之间的数据分割出来,返回一个新的ByteBuffer,同时,mark标记重置为-1。不过这里注意,分割出来的数据的容量恰好就是数据长度,而不是被分割以前的长度。
有时候,咱们只是想要去掉前面一部分,而保留后面一部分数据,同时保持缓冲区的大小不变呢,这里提供一种思路,以下:
public void clearPrePositionData(ByteBuffer byteBuffer) { ByteBuffer buffer2 = byteBuffer.slice(); byteBuffer.clear(); if (buffer2.capacity() > 0) { byteBuffer.put(buffer2); } else { byteBuffer.mark(); byteBuffer.reset(); } byteBuffer.flip(); }