Java NIO之Scatter和Gather
前面的文章分享了Buffer和Channel,以及关于Buffer和Channel的基本操作。这篇文章继续分享关于Channel的Buffer的操作Scatter和Gather,这篇内容比较简单。
什么是Scatter和Gather
Scatter和Gather的字面意思就可以分好的解释他们各自的用途。其中Scatter的意思是分散,Gather的意思是聚集,我们再来看一下他们是如何分散和聚集的,如下图所示
当一个Channel中的数据被多个Buffer来处理,就是分散也就是Scatter。
当多个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();
- 通过RandomAccessFile获得一个FileChannel
- 分别初始化两个ByteBuffer,里面分别放入"hello"和"world"两个字符串。
- 初始化一个ByteBuffer数组,内容为第二步的两个Buffer
- 把ByteBuffer数组里的内容写入到FileChannel
- 关闭RandomAccessFile和FileChannel
执行完以上几步之后,我们打开文件查看就是文本里的内容就是"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();
- 通过RandomAccessFile获得一个FileChannel
- 分别初始化两个ByteBuffer,准备把数据读到这两个buffer里
- 初始化一个ByteBuffer数组,内容为第二步的两个Buffer
- 从FileChannel中读出数据然后写入到ByteBuffer中
- 关闭RandomAccessFile和FileChannel
执行完以上几步之后,输出的内容就是"hello world"
注意:read()方法根据缓冲区数组中的顺序将channel数据写入。一个缓冲区写满后,再往下一个缓冲区写。
使用场景
适用于写入或者读出的数据是固定大小的几部分。