Java NIO中内置了对散播器(scatter)和收集器(gather)的支持。我们知道一个channel可以把数据写到一个buffer中,也可以从一个buffer中把数据写到channel。事实上,一个channel可以同时和多个buffer协作。换句话说,可以把一个channel数据写到多个buffer,也可以读取多个buffer内容到一个channel上
Scatter
我们可以把一个channel中的数据散播到多个buffer,这个过程就是把数据从一个channel写到多个buffer的过程,如下图:

Hello world读入到两个buffer中:
private static void scattering(){
ByteBuffer buffer1 = ByteBuffer.allocate(5);
ByteBuffer buffer2 = ByteBuffer.allocate(5);
ByteBuffer[] buffers = {buffer1,buffer2};
try{
FileChannel channel = new RandomAccessFile("d:\\temp1.txt","rw").getChannel();
while (channel.read(buffers) != -1){
display(buffers);
}
channel.close();
}
catch (IOException e){
e.printStackTrace();
}
}
private static void display(ByteBuffer[] buffers){
for(ByteBuffer buffer: buffers){
buffer.flip();
while (buffer.hasRemaining()){
System.out.print((char) buffer.get());
}
System.out.println();
buffer.clear();
}
}
上面声明了两个ByteBuffer,每个长度都是5,temp.txt内容是:Hello world\r\n。在执行channel.read(buffers)时,channel顺序地填充两个buffer,第一个buffer填满后填充第二个。如果两个都填满后,并且没有读取到文件尾,那么会继续循环填充:
while (channel.read(buffers) != -1){
display(buffers);
}
Gather
对应Scatter,我们也可以把多个buffer中的内容写到同一个channel中,同样也是顺序填充

buffer内容读入到channel中
private static void gathering(){
ByteBuffer buffer1 = ByteBuffer.allocate(6);
buffer1.put("hello ".getBytes());
ByteBuffer buffer2 = ByteBuffer.allocate(6);
ByteBuffer[] buffers = {buffer1,buffer2};
buffer2.put("world!".getBytes());
try{
buffer1.flip();
buffer2.flip();
FileChannel channel = new RandomAccessFile("d:\\temp1.txt","rw").getChannel();
channel.write(buffers);
channel.close();
}
catch (IOException e){
e.printStackTrace();
}
//validation
scattering();
}
上面代码展示了如何把多个buffer内容写道channel中,注意其中要的两行:
buffer1.flip();
buffer2.flip();
因为们先向他们写(put)了数据,此时需要把数据读到channel中,即需要从写模式切换到读模式,所以需要flip。
注意:
Scater一节中的display方法里也有flip(),因为我们向控制台输出的时候其实是先读取buffer内容,所以也要flip
参考
tutorials.jenkov.com/java-nio/sc…
练习
读取本地文件内容,然后实现scatter和gather过程