JAVADOC: java.nio.Buffer
一个用于特定基本类型数据的容器。
缓冲区是特定基本类型元素的线性有限序列。除内容外,缓冲区的基本属性还包括容量、限制和位置:
缓冲区的容量 是它所包含的元素的数量。缓冲区的容量不能为负并且不能更改。
缓冲区的限制 是第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负,并且不能大于其容量。
缓冲区的位置 是下一个要读取或写入的元素的索引。缓冲区的位置不能为负,并且不能大于其限制。
对于每个非 boolean 基本类型,此类都有一个子类与之对应。
传输数据
此类的每个子类都定义了两种获取 和放置 操作:
相对 操作读取或写入一个或多个元素,它从当前位置开始,然后将位置增加所传输的元素数。如果请求的传输超出限制,则相对获取 操作将抛出 BufferUnderflowException,相对放置 操作将抛出 BufferOverflowException;这两种情况下,都没有数据被传输。
绝对 操作采用显式元素索引,该操作不影响位置。如果索引参数超出限制,绝对获取 操作和放置 操作将抛出 IndexOutOfBoundsException。
当然,通过适当通道的 I/O 操作(通常与当前位置有关)也可以将数据传输到缓冲区或从缓冲区传出数据。
做标记和重置
缓冲区的标记 是一个索引,在调用 reset 方法时会将缓冲区的位置重置为该索引。并非总是需要定义标记,但在定义标记时,不能将其定义为负数,并且不能让它大于位置。如果定义了标记,则在将位置或限制调整为小于该标记的值时,该标记将被丢弃。如果未定义标记,那么调用 reset 方法将导致抛出 InvalidMarkException。
不变式
标记、位置、限制和容量值遵守以下不变式:
0 <= 标记 <= 位置 <= 限制 <= 容量
新创建的缓冲区总有一个 0 位置和一个未定义的标记。初始限制可以为 0,也可以为其他值,这取决于缓冲区类型及其构建方式。一般情况下,缓冲区的初始内容是未定义的。
清除、反转和重绕
除了访问位置、限制、容量值的方法以及做标记和重置的方法外,此类还定义了以下可对缓冲区进行的操作:
clear() 使缓冲区为一系列新的通道读取或相对放置 操作做好准备:它将限制设置为容量大小,将位置设置为 0。
flip() 使缓冲区为一系列新的通道写入或相对获取 操作做好准备:它将限制设置为当前位置,然后将位置设置为 0。
rewind() 使缓冲区为重新读取已包含的数据做好准备:它使限制保持不变,将位置设置为 0。
只读缓冲区
每个缓冲区都是可读取的,但并非每个缓冲区都是可写入的。每个缓冲区类的转变方法都被指定为可选操作,当对只读缓冲区调用时,将抛出 ReadOnlyBufferException。只读缓冲区不允许更改其内容,但其标记、位置和限制值是可变的。可以调用其 isReadOnly 方法确定缓冲区是否为只读。
线程安全
多个当前线程使用缓冲区是不安全的。如果一个缓冲区由不止一个线程使用,则应该通过适当的同步来控制对该缓冲区的访问。
调用链
指定此类中的方法返回调用它们的缓冲区(否则它们不会返回任何值)。此操作允许将方法调用组成一个链;例如,语句序列
b.flip();
b.position(23);
b.limit(42);
可以由以下更紧凑的一个语句代替
b.flip().position(23).limit(42);
从以下版本开始:
1.4
--------------------------------------------------------------------------------
按以下例子:
ByteBuffer bb = ByteBuffer.allocate(10); for(int i = 0; i < 9; i++) { bb.put((byte)i); } System.out.println("pos: " + bb.position()); System.out.println("limit: " + bb.limit()); System.out.println("cap: " + bb.capacity()); System.out.println("mark: " + bb.mark()); bb.flip(); // bb.limit(bb.position()).position(0); System.out.println("---------------"); System.out.println("pos: " + bb.position()); System.out.println("limit: " + bb.limit()); System.out.println("cap: " + bb.capacity()); System.out.println("mark: " + bb.mark()); bb.mark(); // bb.mark(bb.position()).position(0); System.out.println("---------------"); System.out.println("pos: " + bb.position()); System.out.println("limit: " + bb.limit()); System.out.println("cap: " + bb.capacity()); System.out.println("mark: " + bb.mark()); bb.clear(); // bb.position(0).limit(10); System.out.println("---------------"); System.out.println("pos: " + bb.position()); System.out.println("limit: " + bb.limit()); System.out.println("cap: " + bb.capacity()); System.out.println("mark: " + bb.mark()); System.out.println("---------------"); bb.limit(); System.out.println("mark: " + bb.mark()); bb.limit(1); System.out.println("mark: " + bb.mark()); bb.put((byte)9); System.out.println("mark: " + bb.mark()); bb.put((byte)10);
将输出:
pos: 9 limit: 10 cap: 10 mark: java.nio.HeapByteBuffer[pos=9 lim=10 cap=10] --------------- pos: 0 limit: 9 cap: 10 mark: java.nio.HeapByteBuffer[pos=0 lim=9 cap=10] --------------- pos: 0 limit: 9 cap: 10 mark: java.nio.HeapByteBuffer[pos=0 lim=9 cap=10] --------------- pos: 0 limit: 10 cap: 10 mark: java.nio.HeapByteBuffer[pos=0 lim=10 cap=10] --------------- mark: java.nio.HeapByteBuffer[pos=0 lim=10 cap=10] mark: java.nio.HeapByteBuffer[pos=0 lim=1 cap=10] mark: java.nio.HeapByteBuffer[pos=1 lim=1 cap=10] Exception in thread "main" java.nio.BufferOverflowException at java.nio.Buffer.nextPutIndex(Buffer.java:495) at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:145) at com.garinzhang.lab.mina.demo4.IoBufferTest.main(IoBufferTest.java:49)
References:
http://www.blogjava.net/killme2008/archive/2008/02/22/181357.html
http://blog.csdn.net/sinboy/article/details/3984459
http://www.cnblogs.com/killbug/archive/2012/11/25/2787717.html
http://www.cnblogs.com/rollenholt/archive/2011/09/29/2195730.html