java NIO ByteBuffer 学习
ByteBuffer看过很多资料。看完很久没有用便忘记了,今天遇到了需要ByteBuffer的场景,就需要复习,于是便写点博客或者程序加深印象,下次直接使用不再需要复习资料。
- ByteBuffer介绍
ByteBuffer的内部字段
- 1.byte[] buff
用来存贮字节数据的数组 - 2.position
当前读写操作的数据位置下标,读写会从这个位置开始,操作完成之后会更新下标的值。 - 3.mark
标记。一个临时变量。当调用mark()方法的时候,mark变量记录当前position的值。后续操作中有reset()方法调用的时候 会将postion回滚到mark的值。mark()与reset()配套使用。 - 4.capacity
容量。这个ByteBuffer的最大容量。 一般在初始化的时候,定义好了capacity;
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//以上代码初始化了一个byteBuffer,这个byteBuffer的初始化大小为1024
5.limit
限制。读写是不能超过该值。默认的情况下,写数据的时候limit==capacity,读数据的时候 limit == buffer中有效数据的长度.
说明:0 <= mark <= position <= limit <= capacity, ByteBuffer中直接操作 limit和capacity,position的方法。/** *直接设置position **/ public final Buffer position(int newPosition) { if ((newPosition > limit) || (newPosition < 0)) throw new IllegalArgumentException(); position = newPosition; if (mark > position) mark = -1; return this; } /* *直接设置limit的值 */ public final Buffer limit(int newLimit) { if ((newLimit > capacity) || (newLimit < 0)) throw new IllegalArgumentException(); limit = newLimit; if (position > limit) position = limit; if (mark > limit) mark = -1; return this; }
除了以上两种方法可以改变postion和limit的值
flip(),clear();
ByteBuffer的内部方法
1.flip();
原码如下:public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
mark标志改为-1;limit改为position,即limit设置当前写入的数据位置。然后数据位置position设置为起始位置
2.clear();
原码如下:public final Buffer clear() { position = 0; limit = capacity; mark = -1; return this; }
mark标志改为-1;数据位置position设置为起始位置,limit设置为缓冲区的容量大小。并非真的清空,如果上次读满,这次未读满,缓冲区就会存在上次处理的数据。判断是否还有可用数据:
public final boolean hasRemaining() { return position < limit; } public final int remaining() { return limit - position; }
另外 compact()方法:
作为抽象方法。在不同子类中有不同的实现。这里得说说ByteBuffer的子类
DirectByteBuffer
HeapByteBuffer
由字面意思我们就可以看出
DirectByteBuffer 是直接操作操作系统内存,HeapByteBuffer是操作堆内存。HeapByteBuffer(int cap, int lim) { // package-private super(-1, 0, lim, cap, new byte[cap], 0); /* hb = new byte[cap]; offset = 0; */ } DirectByteBuffer(int cap) { // package-private super(-1, 0, cap, cap); boolean pa = VM.isDirectMemoryPageAligned(); int ps = Bits.pageSize(); long size = Math.max(1L, (long)cap + (pa ? ps : 0)); Bits.reserveMemory(size, cap); long base = 0; try { base = unsafe.allocateMemory(size); } catch (OutOfMemoryError x) { Bits.unreserveMemory(size, cap); throw x; } unsafe.setMemory(base, size, (byte) 0); if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); } else { address = base; } cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); att = null; }
在 HeapByteBuffer 中的 compact实现:
public ByteBuffer compact() {
System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
position(remaining());
limit(capacity());
return this;
}
该方法的作用是将 position 与 limit之间的数据复制到buffer的开始位置,复制后 position = limit -position,limit = capacity
但如果position 与limit 之间没有数据的话发,就不会进行复制
以下内容来自转载: