更多内容:我的博客
分散(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); //写入数据到channel中 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(); //获取channel FileChannel wirteChannel = writeFile.getChannel(); ){ ByteBuffer header = ByteBuffer.allocate(48); //header缓冲区 ByteBuffer content = ByteBuffer.allocate(1024); //content缓冲区 ByteBuffer[]bufferArray = {header, content}; //组成数组,先读取header,header缓冲区满了以后再读取到content缓冲区 while(readChannel.read(bufferArray) != -1) { for(int i=0; i"); } if(i==1) { System.out.println(); System.out.print("content=>"); } while(bufferArray[i].hasRemaining()) { System.out.print((char)bufferArray[i].get()); } bufferArray[i].rewind(); //将position重置为0,为了下面的聚集读取,具体rewind()方法介绍可参考Java NIO 笔记02中的介绍 } //test1.txt中的内容写入到test2.txt中 wirteChannel.write(bufferArray); for(int i=0; i test1.txt中内容如下:
[-------------this is header parts-------------][----------this is content paras,welcome from www.huhailong.vip---------]控制台运行结果如下:
并且test2.txt中已经存在于test1.txt文件中相同的内容。
更多内容:我的博客欢迎分享,转载请注明来源:内存溢出
评论列表(0条)