Java IO教程 - Java缓冲区读写
缓冲区读取
有两种方法从缓冲区读取数据:
- 绝对位置
- 相对位置
使用四个版本重载的get()方法用于从缓冲区读取数据。
get(int index)返回给定索引处的数据。
get()从缓冲区中的当前位置返回数据,并将位置增加1。
get(byte [] destination,int offset,int length)从缓冲区中批量读取数据。 它从缓冲区的当前位置读取长度字节数,并将它们放在从指定偏移量开始的指定目标数组中。
get(byte [] destination)通过从缓冲区的当前位置读取数据并且每次读取数据元素时将当前位置递增1来填充指定的目标数组。
缓冲区写入
使用重载五个版本的put()方法将数据写入缓冲区。
put(int index,byte b)将指定的b数据写入指定的索引。 调用此方法不会更改缓冲区的当前位置。
put(byte b)将指定的字节写入缓冲区的当前位置,并将位置递增1。
put(byte [] source,int offset,int length)将起始于偏移量的源数组的字节长度写入从当前位置开始的缓冲区。 如果缓冲区中没有足够的空间来写入所有字节,它会抛出BufferOverflowException。 缓冲区的位置按长度增加。
put(byte [] source)与调用put(byte [] source,0,source.length)相同。
ByteBuffer put(ByteBuffer src)从指定的字节缓冲区src读取剩余的字节,并将它们写入缓冲区。 如果目标缓冲区中的剩余空间小于源缓冲区中的剩余字节,则抛出运行时BufferOverflowException。
以下代码显示如何写入缓冲区和从缓冲区读取。
import java.nio.ByteBuffer; public class Main { public static void main(String[] args) { ByteBuffer bb = ByteBuffer.allocate(8); printBufferInfo(bb); for (int i = 50; i < 58; i++) { bb.put((byte) i); } printBufferInfo(bb); } public static void printBufferInfo(ByteBuffer bb) { int limit = bb.limit(); System.out.println("Position = " + bb.position() + ", Limit = " + limit); for (int i = 0; i < limit; i++) { System.out.print(bb.get(i) + " "); } System.out.println(); } }
如果我们可以在缓冲区上使用相对get()或put()方法来读/写至少一个元素,则缓冲区的hasRemaining()方法返回true。
我们可以通过使用相对的get()或put()方法,通过使用其remaining()方法来获得我们可以读/写的最大数量的元素。
上面的代码生成以下结果。
例子
以下代码显示如何使用相对读取和写入之间的缓冲区的flip()和hasRemaining()方法。
import java.nio.ByteBuffer; public class Main { public static void main(String[] args) { ByteBuffer bb = ByteBuffer.allocate(8); printBufferInfo(bb); // Use flip() to reset the position to zero because // the printBufferInfo() method uses relative get() method bb.flip(); int i = 50; while (bb.hasRemaining()) { bb.put((byte) i++); } // Call flip() again to reset the position to zero, // because the above put() call incremented the position bb.flip(); printBufferInfo(bb); } public static void printBufferInfo(ByteBuffer bb) { int limit = bb.limit(); System.out.println("Position = " + bb.position() + ", Limit = " + limit); while (bb.hasRemaining()) { System.out.print(bb.get() + " "); } System.out.println(); } }
上面的代码生成以下结果。
只读缓冲区
缓冲区可以是只读的或读写的。 我们只能读取只读缓冲区的内容。
我们可以通过调用特定缓冲区类的asReadOnlyBuffer()方法来获取只读缓冲区。
// Create a buffer that is read-write by default ByteBuffer bb = ByteBuffer.allocate(1024); boolean readOnly = bb.isReadOnly(); // false
要检查缓冲区是否为只读,请按如下所示调用isReadOnly()方法:
ByteBuffer bbReadOnly = bb.asReadOnlyBuffer(); boolean readOnly = bbReadOnly.isReadOnly();
asReadOnlyBuffer()方法返回的只读缓冲区是同一个缓冲区的不同视图。 对原始缓冲区的内容的任何修改都反映在只读缓冲区中。
缓冲区视图
我们可以获得缓冲区的不同视图。 缓冲区的视图与原始缓冲区共享数据,并保持其自身的位置,标记和限制。
我们也可以复制一个缓冲区,在这种情况下,它们共享内容,但独立地保持标记,位置和限制。 使用缓冲区的duplicate()方法获取缓冲区的副本如下:
// Create a buffer ByteBuffer bb = ByteBuffer.allocate(1024); // Create a duplicate view of the buffer ByteBuffer bbDuplicate = bb.duplicate();
我们还可以通过使用缓冲区的slice()方法创建其切片视图,从而创建缓冲区的切片视图,如下所示:
// Create a buffer ByteBuffer bb = ByteBuffer.allocate(8); bb.position(3); bb.limit(6); // bbSlice will have position set to 0 and its limit set to 3. ByteBuffer bbSlice = bb.slice();
我们还可以获得用于不同原始数据类型的字节缓冲区的视图。
例如,我们可以获得字节缓冲区的字符视图,浮点视图等。ByteBuffer类包含诸如asCharBuffer(),asLongBuffer(),asFloatBuffer()等方法来获得原始数据类型的视图。
// Create a byte buffer ByteBuffer bb = ByteBuffer.allocate(8); // Create a char view of the byte buffer CharBuffer cb = bb.asCharBuffer(); // Create a float view of the byte buffer FloatBuffer fb = bb.asFloatBuffer();