当你写数据到一个buffer,buffer跟踪你写了多少数据。一旦你需要读取数据,你需要调用flip()方法,切换buffer的写模式为读模式。在读模式中buffer允许你读取所有的数据写入buffer。
一旦你读了所有的数据,你需要明确的buffer,让它准备好再次写入。你可以在两个方法:通过调用clear()或通过调用compact()。clear()方法清除整个buffer。compact()方法只是清除你已经读过数据。任何未读数据被移到buffer的头部,数据不会写入未读数据的尾部。
demo:
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
//创建48个字节的buffer
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
//将buffer切换到读模式
buf.flip();
while(buf.hasRemaining()){
System.out.print((char) buf.get()); //每次读取1字节
}
//将buffer切换到写模式
buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();
position和limit属性取决于buffer是读还是写的模式,容量始终是确定的,跟读写的模式无关。图例:
Java NIO有如下的类型:
正如所见,buffer的类型表示不同的数据类型。换句话说,它们允许使用char,short,int,long,float或double来处理缓冲区中的字节.
MappedByteBuffer这个比较特殊,后面会细说。
要获取Buffer对象,必须先分配它。每个Buffer类都有一个allocate()方法来执行此操作。这是一个分类了48字节的ByteBuffer示例:
ByteBuffer buf = ByteBuffer.allocate(48);
下面是一个分配的1024个字符空间的的示例:
CharBuffer buf = CharBuffer.allocate(1024);
你可以通过两种方式往buffer中写入数据:
1. 将数据从Channel中写入到Buffer:
int bytesRead = inChannel.read(buf); //读入缓冲区
buf.put(127);
有很多其他版本的put()方法可以通过不同的方式将数据写入到buffer。比如,在指定位点写入,或者往buffer中写入一个byte数组。可以参阅Java文档获取具体的缓冲区实现。
有两种读取buffer的方法:
1. 从buffer中读取数据到channel
//从缓冲区读入通道。
int bytesWritten = inChannel.write(buf);
byte aByte = buf.get();
有很多其他版本的get()方法可以通过不同的方式从buffer中读取数据。比如,在指定位点读取,或者往buffer中读取字节数组。可以参阅Java文档获取具体的缓冲区实现。
Buffer.rewind()方法将位点设置为0,这样您就可以重读缓冲区中的所有数据。limit保持不变,因此仍然标可以标记有多少个元素(字节,字符等),可以从Buffer中读取。
clear方法
如果Buffer中任有未读到的数据,但是你想稍后读取,先写入一些数据,需要调用compact方法,而不是clear
compact方法
通过调用Buffer.mark()方法你可以在buffer中标记一个给定的位置。这样就可以后续通过调用Buffer.reset()方法将position重置为之前标记的位置。
buffer.mark();
//...
//调用buffer.get()几次。例如在解析期间。
//...
buffer.reset(); //将位置设置回标记。
用于比较两个buffer