##Buffer的基本用法
使用Buffer读写数据一般遵循以下四个步骤:
写入数据到Buffer
调用flip()方法
从Buffer中读取数据
调用clear()方法或者compact()方法
当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。
一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
下面两个例子就是两个方法的区别,compact()需要最后再循环一下,来保证数据被传输完,两个方法对比,即使compact()方法更节省一点,就向写写文章,在上次没写完的地方接着写,而clear()则会重新拿一张新的只开始写
下面的例子是网上找的,我自己有一些疑问channelCopy1 中为什么会存在部分读取的情况,每次 dest.write(buffer);不是都会读取完数据完 从 src中写入的数据吗?应该不会有没读取完的数据啊?
package com.unis.io;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class channelTest {
public static void main(String[] args) throws IOException {
ReadableByteChannel source = Channels.newChannel(System.in);
WritableByteChannel dest = Channels.newChannel(System.out);
channelCopy1(source, dest);
// alternatively, call channelCopy2 (source, dest);
System.out.println(100);
source.close();
dest.close();
}
/**
* Channel copy method 1. This method copies data from the src
* channel and writes it to the dest channel until EOF on src.
* This implementation makes use of compact( ) on the temp buffer * to pack down the data if the buffer wasn't fully drained. This * may result in data copying, but minimizes system calls. It also * requires a cleanup loop to make sure all the data gets sent.
*/
private static void channelCopy1(ReadableByteChannel src,
WritableByteChannel dest)
throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(3 );
while (src.read(buffer) != -1) {
// Prepare the buffer to be drained
buffer.flip();
// Write to the channel; may block
dest.write(buffer);
// If partial transfer, shift remainder down
// If buffer is empty, same as doing clear( )
buffer.compact();
}
// EOF will leave buffer in fill state
buffer.flip();
// Make sure that the buffer is fully drained
while (buffer.hasRemaining()) {
dest.write(buffer);
}
}
/**
* Channel copy method 2. This method performs the same copy, but
* assures the temp buffer is empty before reading more data. This
* never requires data copying but may result in more systems calls.
* No post-loop cleanup is needed because the buffer will be empty
* when the loop is exited.
*/
private static void channelCopy2(ReadableByteChannel src,
WritableByteChannel dest)
throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1) {
// Prepare the buffer to be drained
buffer.flip();
// Make sure that the buffer was fully drained
while (buffer.hasRemaining()) {
dest.write(buffer);
}
// Make the buffer empty, ready for filling
buffer.clear();
}
}
}