Java NIO 的分散(scatter)/聚集(gather)
更多内容:我的博客 分散(scatter)和聚集(gather)是用于从通道读取和写入的概念。从通道分散读取是一种将数据读入多个缓冲区(Buffer)的读取操作,也就是将来自通道的数据分散到多个缓冲区中。
对通道的聚集写入是一种将数据从多个缓冲区写入单个通道的写入操作。因此,通道将来自多个缓冲区的数据“聚集”到一个通道中。在需要分别处理传输数据的各个部分的情况下,分散/聚集是非常有用的。例如,如果消息是由标题和正文组成的,我们可以将标题和正文保存在单独的缓冲区。这样可以轻松的分别处理标题和正文。
分散读取(scatter reads)
将数据从单个通道(channel)读取到多个缓冲区(Buffer)。如下图:
代码:
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[]bufferArray = {header, body};
channel.read(bufferArray);
上面我们首先分配了俩个缓冲区,然后把它们插入到一个bufferArray的数组中,因为channel的read方法除了可以接受ByteBuffer还可以接受ByteBuffer数组,然后read方法会按照缓冲区(buffer)在数组中出现的顺序从channel中写入数据,一旦缓冲区满了以后,通道就会继续填充下一个缓冲区。由于分散读取在进入下一个缓冲区时上一个缓冲区已经被填满,所以它不适合动态大小的消息部分。也就是说如果消息中的header部分的大小是固定的,例如上面代码中的128字节,那么分散读取是适用的。
聚集写入(gather writers)
聚集写入就是从多个缓冲区写入到单个通道中,如图:
代码:
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[]bufferArray = {header, body};
channel.write(bufferArray);
ByteBuffer数组传入write方法后,该方法将缓冲区中的数据按照它们在数组中的顺序写入到channel中。写入时仅写入position到limit的数据,例如我们header定义了128字节,但是实际只有58字节,那么写入时只会写入58字节。因此,与分散读取相比,聚集写入对动态大小的消息部分正常工作。
个人完整实例
该实例展示了分散读取和聚集写入,控制台打印了俩部分内容,并且使用聚集写入将内容复制到另外一个文件内
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ScatterAndGather {
private final static String readFilePath = "C:\\temp\\test1.txt";
private final static String writeFilePath = "C:\\temp\\test2.txt";
public static void main(String[] args) {
scatterReadsAndGatherWrite(readFilePath, writeFilePath);
}
public static void scatterReadsAndGatherWrite(String readFilePath, String writeFilePath) {
try(
RandomAccessFile readFile = new RandomAccessFile(readFilePath, "rw");
RandomAccessFile writeFile = new RandomAccessFile(writeFilePath,"rw");
FileChannel readChannel = readFile.getChannel();
FileChannel wirteChannel = writeFile.getChannel();
){
ByteBuffer header = ByteBuffer.allocate(48);
ByteBuffer content = ByteBuffer.allocate(1024);
ByteBuffer[]bufferArray = {header, content};
while(readChannel.read(bufferArray) != -1) {
for(int i=0; i<bufferArray.length; i++) {
bufferArray[i].flip();
if(i==0) {
System.out.print("header=>");
}
if(i==1) {
System.out.println();
System.out.print("content=>");
}
while(bufferArray[i].hasRemaining()) {
System.out.print((char)bufferArray[i].get());
}
bufferArray[i].rewind();
}
wirteChannel.write(bufferArray);
for(int i=0; i<bufferArray.length; i++) {
bufferArray[i].clear();
}
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
test1.txt中内容如下:
[-------------this is header parts-------------][----------this is content paras,welcome from www.huhailong.vip---------]
控制台运行结果如下:
并且test2.txt中已经存在于test1.txt文件中相同的内容。 更多内容:我的博客
|