Java nio Buffer

Buffer是一块内存,主要用在NIO Channel,比如FileChannel,SocketChannel。

对Channel的读写都是直接操作Buffer对象。

 

Buffer是一个工具类,提供了操作这个内存块的方法。

 

Buffer的实现主要有以下几种:

Buffer的类型:

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

 

Buffer基本使用

四步搞定

  • 写数据到Buffer中
  • 调用buffer.flip()
  • 从buffer中读取数据
  • 调用buffer.clear()或者buffer.compact()

 

buffer主要有四个主要属性:

  • capacity: Buffer最大容量
  • position:读写偏移
  • limit:最大可读容量
  • mark: 标记,可以调用reset重读或重写

只要理解了这四个属性,基本就掌握了Buffer的使用和原理。

 

我们来看下这三个属性的说明:

position和limit依赖于Buffer处于读模式还是写模式,capacity的意义在读模式和写模式都是一样的

  • 1 capacity:Buffer的最大容量

 

  • 2 position位置:写模式下:初始值为0,比如当你put(),putXXX()时,position累加,position最大值是capacity-1

读模式下:调用Buffer.flip从写模式切换到读模式,position被重置为0,其他与写模式的偏移累加一致

 

  • 3 limit:写模式下:limit的值与capacity一致

读模式下:limit用来标志你能够读取多少数据,意思就是你只能读取写入的position数据。

 

  • 4 mark:重置读写偏移

 

读写可以参考下图:

Java nio Buffer


写模式下,posistion累加,limit和capacity不变,即可以写入的最大字数。

每次调用一次put()或者putXXXX()时,position+n(n为你写入的字数,如果写入一个字,则position+1,如果你写入字数组,position+数组.长度)

 

读模式:当调用flip()时,将limit设置为position,position设置为0,mark设置为-1,limit为能够读取的最大字数。

每调用一次get或者getXXX()时,position+n(n为你读取的字数,如果读取一个字,则position+1,如果你读取字数组,position+数组.长度)

 

Capacity在读模式和写模式下都不变。

 

Buffer.clear()和Buffer.compact()

读取完数据后,如果想要Buffer能够再次写入,可以调用clear和compact函数。

 

如果调用clear函数,position设置为0.limit设置为capacity,其实里面的数据并没有被清除,只是覆盖写。

但是有一个场景是,数据没有读取完成之前,你需要要先写入一些数据时,可以调用compact函数,这个函数会把没有读取完的数据拷贝到Buffer开始处,然后把position设置为n(n为未读取数据的长度),limit设置为capacity。

下面是一个简单的Demo:


// 基本使用
// 新建一个缓冲区,可以存放10个整数
IntBuffer intBuffer = IntBuffer.allocate(10);

// 没有元素的时候,注意:get的内容int为0,你有可能put 0,所以可以判断一下position
// 调用intBuffer.position()
// 否则get 会让position+1
System.out.println("current position should be 0, actually: " + intBuffer.position());
if (intBuffer.position() > 0) {
    int empty_get = intBuffer.get();
}

// 连续放入10个元素
intBuffer.put(1);
intBuffer.put(2);
intBuffer.put(3);
intBuffer.put(4);
intBuffer.put(5);
intBuffer.put(6);
intBuffer.put(7);
intBuffer.put(8);
intBuffer.put(9);
intBuffer.put(10);

// 放入第11个元素时会溢出
try {
    intBuffer.put(11);
} catch (BufferOverflowException e) {
    System.out.println("here should be overflow");
    e.printStackTrace();
}

// 写模式切换到读模式
intBuffer.flip();

// 从buffer中读取数据
int one = intBuffer.get();
System.out.println("read from IntBuffer: should be 1, actually: " + one);
// 重定向读取位置为0
intBuffer.rewind();
one = intBuffer.get();
System.out.println("read from IntBuffer: should be 1, actually: " + one);

//intBuffer.get(new int[9]);

// 读模式切换到写模式
// 将position设置为0, limit设置为capacity
// 如果不想继续读取未被读取的数据,intBuffer.clear();
intBuffer.compact();

intBuffer.put(11);

intBuffer.flip();

// 读取第一个元素,应该是2
int two = intBuffer.get();
System.out.println("read from IntBuffer: should be 2, actually: " + two);


上一篇:操作系统概述-脑图笔记


下一篇:流光按钮css3-炫酷