Java NIO - Gather

众所周知,与 Java 的传统 IO API 相比,Java NIO 是一种针对数据 IO 操作更优化的 API。Java NIO 提供的另一个额外支持是从多个缓冲区到通道读取/写入数据。这种多次读写支持称为分散和聚集,其中,在读取数据的情况下,数据从单个通道分散到多个缓冲区,而在写入数据的情况下,数据从多个缓冲区收集到单个通道。

为了实现从通道的多次读写,Java NIO 提供了 ScatteringByteChannel 和 GatheringByteChannel API 来读写数据,如下例所示。

GatheringByteChannel

写入多个通道 −在此,我们将多个缓冲区中的数据写入单个通道。为此,再次分配多个缓冲区并将其添加到缓冲区类型数组中。然后,将此数组作为参数传递给 GatheringByteChannel write() 方法,该方法随后按照缓冲区在数组中出现的顺序从多个缓冲区中写入数据。这里要记住的一点是,只写入缓冲区位置和边界之间的数据。

以下示例显示了如何在 Java NIO 中执行数据收集

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;

public class GatherExample {
   private static String FILENAME = "C:/Test/temp.txt";
   public static void main(String[] args) {
    String stream1 = "首先收集数据流";
    String stream2 = "其次收集数据流";
    ByteBuffer bLen1 = ByteBuffer.allocate(1024);
    ByteBuffer bLen2 = ByteBuffer.allocate(1024);
    // 接下来的两个缓冲区保存我们要写入的数据
    ByteBuffer bstream1 = ByteBuffer.wrap(stream1.getBytes());
    ByteBuffer bstream2 = ByteBuffer.wrap(stream2.getBytes());
    int len1 = stream1.length();
    int len2 = stream2.length();
    // 将长度(数据)写入缓冲区
    bLen1.asIntBuffer().put(len1);
    bLen2.asIntBuffer().put(len2);
    System.out.println("Gathering :Len1 = " + len1);
    System.out.println("Gathering :Len2 = " + len2);
    // 将数据写入文件
      try { 
         FileOutputStream out = new FileOutputStream(FILENAME);
         GatheringByteChannel gather = out.getChannel();						
         gather.write(new ByteBuffer[] {bLen1, bLen2, bstream1, bstream2});
         out.close();
         gather.close();
      }
      catch (FileNotFoundException exObj) {
         exObj.printStackTrace();
      }
      catch(IOException ioObj) {
         ioObj.printStackTrace();
      }
   }
}

输出

Gathering : Len1 = 24
Gathering : Len2 = 25

最后可以得出结论,Java NIO 中的分散/聚集方法在正确使用时是一种优化和多任务的方法。它允许您将繁重的工作委托给操作系统,即将读取的数据分离到多个存储桶中,或将不同的数据块组装成一个整体。毫无疑问,通过避免缓冲区复制,这可以节省时间并更有效地使用操作系统,并减少需要编写和调试的代码量。