Java NIO的Buffer用于和channel进行交互。
buffer本质上是一个内存块,你可以写数据,然后读取出来。
这个内存块是通过NIO的Buffer对象进行包装的,该对象提供了一系列的方法,使得对内存块的访问更加容易了。
基本的Buffer使用
使用Buffer读写数据一般有如下4步:
1、将数据写入 Buffer
2、调用buffer.flip()方法
3、从Buffer中读出数据
4、调用buffer.clear()方法或buffer.compact()方法
当你将数据写入buffer,它会记录你写入了多少数据。一旦你去读数据的时候,你需要反转buffer,通过flip方法,将buffer从写模式转为读模式。在读模式中,buffer允许你读取所有写进去的数据。
一旦你读取了所有的数据,你需要清除buffer,让它再一次为写做好准备,有两种方式:clear()或compact()。clear清除了整个buffer,compact仅仅清除你已经读过的数据。其它未读数据将被移动到buffer的头部,现在写入的数据就会在未读的数据之后。
实例:
注意代码中flip,clear等的调用顺序
Buffer的capacity,position和limit
Buffer有三个属性,如上所示
position和limit依赖于Buffer是在读模式还是写模式。Capacity无关模式,总是相同的。
看一张图
Capacity
Buffer有固定的大小,叫做capacity,又可以写capacity个字节类型,长整型,字符型等数据,写入buffer。一旦buffer满了,在写入数据之前,你需要置空它(读或者清除)。
Position
当你把数据写入Buffer,就会写到了某个position。position初始为0。当数据写入了,position就会指向写一个插入数据的位置。position最大值为capacity-1。
当你从Buffer中读数据,你也是从某个position开始读。当你flip一个缓冲区从写模式到读模式,position就被重置为0了。读数据的时候,position也会一直移动,指向下一个读的位置。
Limit
在写模式中,limit代表你可以写入多少数据,等于buffer的capacity。
当你flip为写模式的时候,limit代表你可以读出多少数据,因此当flip为读模式,limit被设置为写模式中的position。换句话说,你可以读取写入过的所有数据。
Buffer Types
Java NIO中提供如下Buffer类型:
·ByteBuffer
·MappedByteBuffer
·CharBuffer
·DoubleBuffer
·FloatBuffer
·IntBuffer
·LongBuffer
·ShortBuffer
这些Buffer类型代表不同的数据类型。MappedByteBuffer在后续章节会说。
Allocating a Buffer
为了获取一个Buffer对象,你必须首先分配一块空间。每一个Buffer类都有一个allocate方法。
ByteBuffer buf = ByteBuffer.allocate(48);
CharBuffer buf = CharBuffer.allocate(1024);
Writing Data to a Buffer
写数据到buffer有两种方式:
1、从channel写数据到buffer
2、通过buffer的put方法给自己写数据
int bytesRead = inChannel.read(buf); //read into buffer.
buf.put(127);
flip()
flip方法将缓冲区从写模式转成读模式。调用flip方法将position设置为0,将limit设置为position刚刚之前的位置。
换言之,position现在是读的位置,limit是读的最多限制。
Reading Data from a Buffer
同样两种方式可以从buffer中读数据:
1、将数据从buffer中读到channel中
2、通过get方法从自己读
//read from buffer into channel.
int bytesWritten = inChannel.write(buf);
byte aByte = buf.get();
rewind()
该方法设置position为0,所以你可以重新读buffer中的所有数据了。limit保持不变,仍然表示可以从buffer中读取多少数据。
clear() and compact()
一旦你读完了buffer的数据,你必须再次将buffer准备好写,通过clear或者compact方法。
clear方法将position设置为0,limit设置为capacity。换言之,buffer清理了,buffer中数据并未清除,只是标记告诉你从哪开始写数据。
如果有任何未读的数据,当你调用clear方法,数据将被忽略。无法找回。
如果仍然有数据未读,但是你想稍后再读取,你可以调用compact而不是clear。
compact方法将所有未读数据移动到buffer的头部,设置position未未读数据的最后一个位置,limit=capacity。现在buffer准备写,但是未读数据不会被重写。
mark() and reset()
可以通过mark方法去标记一个buffer中position,稍后你可以通过reset方法将position设置你刚刚标记的位置。
buffer.mark();
//call buffer.get() a couple of times, e.g. during parsing.
buffer.reset(); //set position back to mark.
equals() and compareTo()
比较两个buffer是否相等。
equals()
两个buffer如果相等,满足如下条件:
1、类型相同
2、buffer中内容空间相同
3、buffer中内容相同
compareTo()
该方法比较buffer中内容,比如排序等等
1、