Java NIO之Scatter/Gather

/ Java / 没有评论 / 320浏览

前面的文章分享了Buffer和Channel,以及关于Buffer和Channel的基本操作。这篇文章继续分享关于Channel的Buffer的操作Scatter和Gather,这篇内容比较简单。

什么是Scatter和Gather

Scatter和Gather的字面意思就可以分好的解释他们各自的用途。其中Scatter的意思是分散,Gather的意思是聚集,我们再来看一下他们是如何分散和聚集的,如下图所示

http://p0.qhimg.com/t01895a48daee5ddf26.png

当一个Channel中的数据被多个Buffer来处理,就是分散也就是Scatter。

http://p0.qhimg.com/t0153b1b83296c390d7.png

当多个Buffer同时向一个Channel中写数据时,就是聚集也就是Gather。

如何使用

我们用FileChannel来解释如何使用Scatter和Gather。

Gather

RandomAccessFile randomAccessFile = new RandomAccessFile(
		"/Users/yangpeng/Documents/360/code/QiwooSample/NIOSample/src/com/nio/sample/file.txt", "rw");
randomAccessFile.seek(0);

FileChannel fileChannel = randomAccessFile.getChannel();
System.out.println("FileChannel position " + fileChannel.position());

ByteBuffer buffer = ByteBuffer.allocate(100);
String str = "hello";
buffer.clear();
buffer.put(str.getBytes());
buffer.flip();

ByteBuffer buffer2 = ByteBuffer.allocate(100);
String str2 = " world";
buffer2.clear();
buffer2.put(str2.getBytes());
buffer2.flip();

ByteBuffer[] bufferArray = { buffer, buffer2 };
fileChannel.write(bufferArray);

randomAccessFile.close();
fileChannel.close();

执行完以上几步之后,我们打开文件查看就是文本里的内容就是"hello world"

注意:写入的是缓冲区position和limit之间的数据。如果一个缓冲区容量为10字节,但是仅有5字节的数据,那么写入到通道中的数据就是5个字节。

Scatter

RandomAccessFile randomAccessFile = new RandomAccessFile(
		"/Users/yangpeng/Documents/360/code/QiwooSample/NIOSample/src/com/nio/sample/file.txt", "rw");
randomAccessFile.seek(0);

FileChannel fileChannel = randomAccessFile.getChannel();

ByteBuffer buffer = ByteBuffer.allocate(5);

ByteBuffer buffer2 = ByteBuffer.allocate(100);

ByteBuffer[] bufferArray = {buffer, buffer2};

fileChannel.read(bufferArray);

buffer.flip();
while (buffer.hasRemaining()) {
	System.out.print((char) buffer.get());
}

System.out.println("");

buffer2.flip();
while (buffer2.hasRemaining()) {
	System.out.print((char) buffer2.get());
}

randomAccessFile.close();
fileChannel.close();

执行完以上几步之后,输出的内容就是"hello world"

注意:read()方法根据缓冲区数组中的顺序将channel数据写入。一个缓冲区写满后,再往下一个缓冲区写。

使用场景

适用于写入或者读出的数据是固定大小的几部分。

本文demo