Java NIO中的buffer用于与NIO通道互动。如你所知,数据从通道读入缓冲区,从缓冲区写入通道。
缓冲区本质上是一个内存,可以写入数据,然后读取数据。这个内存被包装成NIO buffer对象提供了一组方法,方便访问该内存。
以下是NIO 与buffer相关的话题列表:Buffer的基本用法 buffercapacity,position和limit buffer类型 Buffer的分配 在buffer中写数据 flip()方法 从buffer中读取数据 clear()compact()方法 mark()和reset()方法 equals()compareto()方法 Buffer的基本用法
使用buffer读写数据一般遵循以下四个步骤: 将数据写入Buffer 调用flip()方法 从buffer中读取数据 调用clear()方法或者compact()方法
当将数据写入buffer时,bufffer将记录多少数据。一旦要读取数据,就需要通过flip()将buffer从写作模式切换到读取模式。在阅读模式下,可以读取之前写入buffer的所有数据。
一旦读完所有数据,就需要清空缓冲区,这样才能再次写入。清空缓冲区有两种方法:调用clear()或compact()。clear()方法将清空整个缓冲区。compact()方法只会清除已读数据。任何未读数据都会移动到缓冲区的起点,新写入的数据会放在缓冲区未读数据的后面。
以下是使用buffer的例子: 01Randomacesfile aFile = new RandomAccessFile("data/nio-data.txt", "rw");Channel202File inChannel = aFile.getChannel();03 04//create buffer with capacity of 48 Bufferbytes05Byte buf = ByteBuffer.allocate(48);06 07int bytesRead = inChannel.read(buf); //read into buffer.08while (bytesRead != -1) {09 10 buf.flip(); //make buffer ready for read11 12 while(buf.hasRemaining()){13 System.out.print((char) buf.get()); // read 1 byte at a time14 }15 16 buf.clear(); //make buffer ready for writing17 bytesRead = inChannel.read(buf);18..close(); buffercapacity,position和limit
缓冲区本质上是一个内存,可以写入数据,然后读取数据。这个内存被包装成NIO buffer对象提供了一组方法,方便访问该内存。
要了解buffer的工作原理,需要熟悉其三个属性: capacity position limit
position和limit的含义取决于buffer的阅读模式或写作模式。无论buffer处于什么模式,capacity的含义总是一样的。
这里有一个关于读写模式中capacity、position和limit的解释,详细解释在插图后面。
capacity
Buffer作为一个内存块,有一个固定的大小值,也称为“capacity”.你只能写capacityby、long,char等类型。一旦buffer满了,就需要清空它(通过阅读数据或清除数据),然后继续写数据来写数据。position
当您将数据写入buffer时,position表示当前位置。最初的position值为0。当一个byter时、buffer写下long等数据后, position将向前移动到下一个可插入数据的bufer单元。position最大可以是capacity – 1.
读取数据时,也从特定位置读取。当Buffer从写作模式切换到读取模式时,position将被重置为0. 从buffer的position读取数据时,position向前移动到下一个可读位置。limit
在写作模式下,buffer的limit表示您最多可以在buffer中写多少数据。 在写作模式下,limit等于buffer的capacity。
将buffer切换到读取模式时, limit表示你最多能读到多少数据。因此,将buffer切换到读取模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)buffer类型
Java NIO 以下Buffer类型 ByteBuffer MappedByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer
p<> 正如你所看到的,这些buffer类型代表不同的数据类型。换句话说,它可以通过char,short,int,long,float 或 缓冲区内的字节由double类型操作。
MappedByteBuffer 有些特别的,在涉及它的特别章节中。Buffer的分配
要想获得buffer对象,首先要分配。 每个buffer类都有一个allocate方法。以下是Bytebuffer分配48字节capacity的例子。 ByteBuffer buf = ByteBuffer.allocate(48);
这是Charbuffer,可以存储1024个字符: 1charbuffer buf = CharBuffer.allocate(1024); 在buffer中写数据
将数据写到buffer有两种方式: 从Channel到buffer。 buffer的put()方法写入buffer。
从Channel到Buffer的例子 int bytesRead = inChannel.read(buf); //read into buffer.
Buffer的例子是通过put写的: buf.put(127);
put方法有很多版本,允许您以不同的方式将数据写入bufer。例如, 写一个指定的位置,或者在buffer中写一个字节数组。 Buffer实现的更多细节参考Javadoc。flip()方法
flip方法将buffer从写作模式切换到读取模式。调用flip()方法将position设置为0,并将limit设置为之前position的值。
换句话说,position现在用来标记阅读位置,limit说之前写了多少byte、char等 —— 现在能读多少byte?、char等。从buffer中读取数据
有两种方法可以从buffer中读取数据: 从buffer读取数据到channel。 使用get()方法从buffer中读取数据。
从Buffer读取数据到Channel的例子: 1//read from buffer into channel.2int bytesWritten = inChannel.write(buf);
使用get()方法从buffer中读取数据的例子 byte aByte = buf.get();
获取方法有很多版本,允许你以不同的方式从buffer中读取数据。比如从指定的position读取,或者从buffer读取数据到字节数组。有关buffer实现的更多细节,请参考Javadoc。rewind()方法
Buffer.rewind()将position设置为0,因此您可以重读buffer中的所有数据。limit保持不变,仍然表示您可以从buffer中读取多少元素(byte、char等。).clear()compact()方法
一旦阅读了buffer中的数据,就需要准备好buffer再次写入。可以通过clear()或compact()来完成。
如果调用clear()方法,position将设置为0,limit将设置为 capacity的价值。换句话说,Buffer 它被清空了。buffer中的数据没有被清除,但这些标记告诉我们可以从哪里开始将数据写入buffer。
如果buffer中有一些未读数据,并调用clear()方法,数据将被“遗忘”,这意味着没有标记会告诉你读过哪些数据,哪些数据还没有读过。
如果buffer中仍有未读数据,并且后续需要这些数据,但此时想先写一些数据,则使用compact()方法。
compact()方法将所有未读数据复制到buffer的起点。然后将position设置在最后一个未读元素的正后面。limit属性仍然像clear()方法一样设置为capacity。现在buffer已经准备好写数据了,但不会覆盖未读数据。mark()和reset()方法
通过调用bufferer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用bufferer.reset()方法恢复到这个position。例如: buffer.mark();//call buffer.get() a couple of times, e.g. during parsing.buffer.reset(); //set position back to mark. equals()compareto()方法
两个buffer可以使用equals()和compareto()。equals()
当满足以下条件时,表示两个buffer相等: 类型相同(byte、char、int等。). buffer中剩余的byter、char等数量相等。 buffer中所有剩余的byter、char等都一样。
正如你所看到的,equals只是比较buffer的一部分,并不是每个元素都比较。事实上,它只比较buffer中的剩余元素。compareTo()方法
compareTo()比较两个buffer的剩余元素的方法(byte、char等), 如果满足以下条件,则认为一个buffer“小于”另一个buffer: 第一个不相等的元素小于另一个buffer中对应的元素 。 所有元素都是相等的,但是第一个buffer比另一个先耗尽(第一个buffer的元素比另一个少)。
(译注:剩余元素来源于 position与limit之间的元素)