Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
NIO中的关键Buffer实现有:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer,分别对应基本数据类型: byte, char, double, float, int, long, short。当然NIO中还有MappedByteBuffer, HeapByteBuffer, DirectByteBuffer等这里先不进行陈述。
首先我们先创建一个Buffer
//create buffer with capacity of 11bytes
ByteBuffer buf = ByteBuffer.allocate(11);
可以把Buffer简单地理解为一组基本数据类型的元素列表,它通过几个变量来保存这个数据的当前位置状态:
索引 | 说明 |
---|---|
capacity | 缓冲区数组的总长度 |
position | 下一个要操作的数据元素的位置 |
limit | 所有对Buffer读写操作都会以limit变量的值作为上限。 |
我们通过ByteBuffer.allocate(11)方法创建了一个11个byte的数组的缓冲区,初始状态如上图,position的位置为0,capacity和limit默认都是数组长度。当我们写入5个字节时,变化如下图:
这时我们需要将缓冲区中的5个字节数据写入Channel的通信信道,所以我们调用ByteBuffer.flip()方法,变化如下图所示(position设回0,并将limit设成之前的position的值):
这里再次解释一下limit:
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。
clear方法
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
clear将缓冲区清空,一般是在重新写缓冲区时调用。
flip方法
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
首先将limit设置为当前位置,然后将position设置为 0。如果已定义了标记。 常与compact方法一起使用。通常情况下,在准备从缓冲区中读取数据时调用flip方法。
compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。
hasRemaining
public final boolean hasRemaining() {
return position < limit;
}
package com.hutonm.nio;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.RandomAccess;
public class Niotest {
@Test
public void method1(){
RandomAccessFile aFile = null;
try {
aFile = new RandomAccessFile("src/nio.text","rw");
FileChannel fileChannel = aFile.getChannel();
//create buffer with capacity of 1024 bytes
ByteBuffer buf = ByteBuffer.allocate(1024);
//read into buffer
int byteRead = fileChannel.read(buf);
// print byteRead
//System.out.println(byteRead);
while (byteRead != -1){
//make buffer read for read
buf.flip();
while (buf.hasRemaining()){
System.out.print((char)buf.get());
}
//清除已读数据
buf.compact();
byteRead = fileChannel.read(buf);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
参考:
http://www.importnew.com/19816.html
http://ifeve.com/buffers/