Java NIO--Buffers

Buffer介绍

Buffer是一个包含了固定大小的特定原生类型数据的容器。定义了标示可读和可写范围的指示器,以及,clearing/flipping/rewinding等方法来标记当前操作位置、重置位置到之前标记的位置。

除了boolean类型所有的原生类型都有一个buffer类与之对应。每个buffer类定义了一系列get/put方法来获取或者插入数据;定义了压缩、复制、切分的方法。以及静态方法来创建一个新的buffer或者将现有的数组放到一个buffer。
ByteBuffer可以作为IO的输入源或输出目标。
ByteBuffer可以是direct buffer,更加高效。
ByteBuffer可以直接从文件映射到内存,MappedByteBuffer。
ByteBuffer可以根据big-endian/little-endian读取或写入非boolean的原生类型数据。

Buffer抽象类源码

public abstract class Buffer {

     // 0 <= mark <= position <= limit <= capacity
    private int mark = -1;//标记的位置
     private int position = 0;//下一个读取或者写入的元素的位置
     private int limit;//可以读取或者写入的最大值+1(第一个不允许读或者写)
     private int capacity;//buffer的大小,值固定。

     // Used only by direct buffers
     // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
     long address;

     //构造方法
     Buffer(int mark, int pos, int lim, int cap) { // package-private
          if (cap < 0)
               throw new IllegalArgumentException();
          this.capacity = cap;
          limit(lim);
          position(pos);
          if (mark >= 0) {
               if (mark > pos)
                    throw new IllegalArgumentException();
               this.mark = mark;
          }
     }

     //相当于get方法
     public final int capacity() {
          return capacity;
     }

     public final int position() {
          return position;
     }
     
     public final int limit() {
          return limit;
     }

     //相当于set方法
     public final Buffer position(int newPosition) {
          //newPosition不能大于当前的limit
          if ((newPosition > limit) || (newPosition < 0))
               throw new IllegalArgumentException();
          position = newPosition;
          //如果新位置小于mark,mark=-1
          if (mark > position)
               mark = -1;
          return this;
     }

     public final Buffer limit(int newLimit) {
          //newLimit必须<=capacity
          if ((newLimit > capacity) || (newLimit < 0))
               throw new IllegalArgumentException();
          limit = newLimit;
          //如果limit减小了小于了position
          if (position > limit)
               position = limit;
          if (mark > limit)
               mark = -1;
          return this;
     }
     //标记当前位置
     public final Buffer mark() {
          mark = position;
          return this;
     }

     //重置,position变为之前mark()操作设置的mark
     public final Buffer reset() {
          int m = mark;
          //没有调用过mark()方法
          if (m < 0)
               throw new InvalidMarkException();
          position = m;
          return this;
     }
     //清空buffer,所有数据不能再读了,可以写入。
     public final Buffer clear() {
          position = 0;
          limit = capacity;
          mark = -1;
          return this;
     }
     //翻转buffer,写入完成,可以读取。
     public final Buffer flip() {
          limit = position;
          position = 0;
          mark = -1;
          return this;
     }
     //写入完成,可以读取,limit需要保证已经提前设置
     public final Buffer rewind() {
          position = 0;
          mark = -1;
          return this;
     }
     //剩余可读取或者可写入的数量
     public final int remaining() {
          return limit - position;
     }
     //是否可写入或者可读
     public final boolean hasRemaining() {
          return position < limit;
     }

     //是否只读
     public abstract boolean isReadOnly();
     //是否是由数组实现
     public abstract boolean hasArray();
     //如果是有数组实现且buffer不是只读buffer返回数组。
     public abstract Object array();
     //buffer的第一个元素在array中的位置??
     public abstract int arrayOffset();
     //是否是direct buffer
     public abstract boolean isDirect();

     // -- Package-private methods for bounds checking, etc. --
     //获得下一个读取的位置,且位置+1
     final int nextGetIndex() {
          if (position >= limit)
               throw new BufferUnderflowException();
          return position++;
     }
       //获得下一个读取的位置,且位置+nb
     final int nextGetIndex(int nb) {
          if (limit - position < nb)
               throw new BufferUnderflowException();
          int p = position;
          position += nb;
          return p;
     }
     //获取下一个插入位置,且位置+1
     final int nextPutIndex() {
          if (position >= limit)
               throw new BufferOverflowException();
          return position++;
     }
     //获取下一个插入位置,且位置+nb
     final int nextPutIndex(int nb) {
          if (limit - position < nb)
               throw new BufferOverflowException();
          int p = position;
          position += nb;
          return p;
     }
    //检查位置是否合法
     final int checkIndex(int i) {
          if ((i < 0) || (i >= limit))
               throw new IndexOutOfBoundsException();
          return i;
     }
     final int checkIndex(int i, int nb) {
          if ((i < 0) || (nb > limit - i))
               throw new IndexOutOfBoundsException();
          return i;
     }
     final int markValue() { 
          return mark;
     }
     final void truncate() {
          mark = -1;
          position = 0;
          limit = 0;
          capacity = 0;
     }
     //检查范围,从off开始读取len的数据,是否超出了size
     static void checkBounds(int off, int len, int size) {
          if ((off | len | (off + len) | (size - (off + len))) < 0)
               throw new IndexOutOfBoundsException();
     }
}

Buffer以及各子类


1:ByteBuffer

是个抽象类

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html

提供的操作:
1:绝对和相对位置的单个字节的get/put方法
2:相对位置的批量字节的get
3:相对位置的批量字节的put
4:绝对和相对位置的其他原生类型的get/put方法【涉及byte order】
5:获取其他原生类型的视图buffer
6:压缩、复制、切片buffer


ByteBuffer可以通过静态方法allocation方法创建一定capacity的buffer,或者包装现有的byte array
ByteBuffer有两类:direct/non-direct。direct buffer直接在操作系统内存分配,non-direct  buffer在jvm 堆中分配。direct buffer的IO直接在操作系统内存操作,避免了操作系统内容和堆内存的复制开销,效率高。但是创建和销毁代价比较高;
direct buffer可以通过allocateDirect静态方法创建;也可以通过file的mapping方法创建;

除了boolean其他的原生类型,都可以直接读写buffer,数据类都占用多个字节,要注意直接的顺序(ByteOrder定义,BIG_ENDIAN).
绝对位置的读写: float  getFloat() void  putFloat(float f)对buffer的当前position操作;
相对位置的读写:float  getFloat(int index)void  putFloat(int index, float f) 从第index个字节开始读写。
视图buffer:
可以通过asFloatBuffer类似的方法创建FloateBuffer等视图buffer,内部仍然是以byte buffer实现。
视图Buffer的index不是指字节而是原生数据

1.1 MappedByteBuffer
http://docs.oracle.com/javase/7/docs/api/java/nio/MappedByteBuffer.html
也是一个抽象类。
一个direct buffer,内容是映射的文件的一部分。
通过FileChannel.map方法创建。
A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.【?direct buffer也受到GC的控制吗】
MappedByteBuffer的内容会动态发生变化,如果映射文件的内容发生变化。何事发生变化、是否发生变化是于操作系统相关的。
MappedByteBuffer的内容可能会不可操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值