目录:

Java NIO 学习笔记(一)----概述,Channel/Buffer

Java NIO 学习笔记(二)----聚集和分散,通道到通道

Java NIO 学习笔记(三)----Selector

Java NIO 学习笔记(四)----文件通道和网络通道

Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe

Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel

Java NIO 学习笔记(七)----NIO/IO 的对比和总结

Scatter / Gather 通道的聚集和分散操作

NIO 具有内置的 scatter/gather 支持,用于描述读取和写入通道的操作。

  • 分散(scatter)地从 Channel 中读取是将数据读入多个 Buffer 的操作。 因此,通道将来自通道的数据“分散”到多个缓冲区中。
  • 聚集(gather)地写入 Channel 是将来自多个缓冲区的数据写入单个通道的操作。 因此,通道将来自多个缓冲区的数据“收集”到同一个通道中。

通道的聚集和分散操作在需要将传输的数据分开处理的场合非常有用,例如,如果消息由标题和正文组成,则可以将标题和正文保留在单独的缓冲区中,这样做可以更容易处理标题和正文。

Scattering Reads 分散读取

是指将数据从单个通道读入多个缓冲区:

下面是一个代码示例,演示如何执行分散读取:

public class ScatteringReads {
public static void main(String[] args) throws IOException { ByteBuffer buffer1 = ByteBuffer.allocate(5); // 分配第一个缓冲区,大小为 5
ByteBuffer buffer2 = ByteBuffer.allocate(128);
ByteBuffer[] buffers = {buffer1, buffer2}; // 两个缓冲区的数组 File file = new File("D:\\test\\1.txt"); // 文件内容是 012345678
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
FileChannel channel = accessFile.getChannel(); long data = channel.read(buffers); // 一次性把通道的数据读入2个缓冲区
System.out.println("Read: " + data); // Read 9 System.out.println("开始读取第一个 buffer :");
buffer1.flip(); // 将 buffer 从写入模式切换为读取模式
while (buffer1.hasRemaining()) {
System.out.print((char) buffer1.get()); // 每次读取1byte,输出 01234
} System.out.println("\n开始读取第二个 buffer :"); buffer2.flip();
while (buffer2.hasRemaining()) {
System.out.print((char) buffer2.get()); // 输出 5678
}
}
}

将会输出:

Read: 9
开始读取第一个 buffer :
01234
开始读取第二个 buffer :
5678

注意多个缓冲区首先插入到数组中,然后将数组作为参数传递给 channel.read() 方法。 然后,read()方法按照缓冲区在数组中出现的顺序从通道写入数据。 一旦缓冲区已满,通道就会继续填充下一个缓冲区。

分散读取在移动到下一个缓冲区之前,必须先填充慢前一个缓冲区,这意味着它不适合大小不固定的消息。

Gathering Writes 聚集写入

“聚集写入”将来自多个缓冲区的数据写入单个通道:

一个示例:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body };
//write data into buffers... channel.write(bufferArray);

将缓冲区数组传递给 write() 方法,该方法按照在数组的顺序写入缓冲区的内容到单个通道,注意仅写入缓冲区的 position 和 limit 之间的数据。 因此,如果缓冲区的容量为 128 字节,但只包含 58 字节的内容,则只有 58 字节从该缓冲区写入通道。 因此,与 Scattering Reads 相比,Gathering Writes 可以适应大小不固定的数据,因为它只把包含内容部分的缓冲区写入到通道。

Channel to Channel 通道到通道传输

在 NIO 中,如果其中一个通道是 FileChannel ,可以直接将数据从一个通道传输到另一个通道。 FileChannel 类有一个 transferTo() 和 transferFrom() 方法。

transferFrom() 和 transferTo()

FileChannel 对象的 transferFrom() 方法将数据从源通道传输到 FileChannel。 这是一个简单的例子:

public class TransfetExample {
public static void main(String[] args) throws IOException {
RandomAccessFile fromFile = new RandomAccessFile("D:\\test\\input.txt", "rw");
FileChannel fromChannel = fromFile.getChannel(); RandomAccessFile toFile = new RandomAccessFile("D:\\test\\receive.txt", "rw");
FileChannel toChannel = toFile.getChannel(); long position = 0;
long count = fromChannel.size(); toChannel.transferFrom(fromChannel, position, count);
}
}

参数 position 和 count,告诉目标文件中开始写入的位置以及最大传输的字节数(总数)。 如果源通道的字节数少于 count ,则传输实际字节数。

此外,一些 SocketChannel 实现可能现在只传输 SocketChannel 在其内部缓冲区中准备好的数据 - 即使 SocketChannel 可能稍后有更多可用数据。 因此,它可能不会将请求的整个数据(count)从 SocketChannel 传输到 FileChannel 。

transferTo() 方法的效果除了目标和参数位置不一致,其他部分同 transferFrom() 方法一样,上面代码如果换成执行 fromChannel.transferTo(position, count, toChannel); input.txt 的内容同样会被立即复制到 receive.txt。

Java NIO 学习笔记(二)----聚集和分散,通道到通道的更多相关文章

  1. JAVA NIO学习笔记二 频道和缓冲区

    Java NIO 频道 Java NIO渠道类似于流,他们之间具有一些区别的: 您可以读取和写入频道.流通常是单向(读或写). 通道可以异步读取和写入数据. 通道常常是读取或写入缓冲区. 如上所述,您 ...

  2. Java NIO 学习笔记(七)----NIO/IO 的对比和总结

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  3. Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  4. Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  5. Java NIO 学习笔记(四)----文件通道和网络通道

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  6. Java NIO 学习笔记(三)----Selector

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  7. Java NIO 学习笔记(一)----概述,Channel/Buffer

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  8. Java NIO学习笔记

    Java NIO学习笔记 一 基本概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执 ...

  9. Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer

    作者:Grey 原文地址:Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer ByteBuffer.allocate()与ByteBuffer.allocateD ...

随机推荐

  1. 【转】mac版微信web开发者工具(小程序开发工具)无法显示二维码 解决方案

    转自:https://www.cnblogs.com/stevenluo/p/6030445.html   微信小程序概念的提出,绝对可以算得上中国IT界惊天动地的一件大事,这可能意味着一场新的开发热 ...

  2. 从JDBC到commons-dbutils

    1.前言 玩过Java web的人应该都接触过JDBC,正是有了它,Java程序才能轻松地访问数据库.JDBC很多人都会,但是为什么我还要写它呢?我曾经一度用烂了JDBC,一度认为JDBC不过如此,后 ...

  3. Matlab Tricks(二十六)—— 置乱(随机化)与恢复(shuffle/permutation & restore)

    x = 1:10; n = length(x); perm = randperm(n); x_perm = x(perm); % x_perm 表示置乱后的结果 x_ori(perm) = x_per ...

  4. window7使用MinGW在命令行编译C/C++源程序(从零开始,设置PATH,LIBRARY_PATH,C_INCLUDE_PATH)

    1.要想在window命令行下面编译C/C++源程序,对于初学者来说,需要在window环境下面配置好GCC和G++编译器,我使用的是MinGW,下载地址为:http://sourceforge.ne ...

  5. uboot初体验-----趣谈nand设备发起的浅显理解

    1 选择Uboot版本号 2 移植uboot至console正常work 3 制造uImage和使用uboot指南 4 写NFC驱动器 5 uboot从nand启动引导系统 1 选择Uboot版本号 ...

  6. 获取 UIElement 相对于屏幕原点所占用的矩形区域

    原文:获取 UIElement 相对于屏幕原点所占用的矩形区域 <Grid Background="Transparent"> <StackPanel Margi ...

  7. 关于JSP

    JSP的本质 JSP本质上就是Servlet, 正常情况下, 它会在第一次被访问的时候被容器转化成Java代码, 然后再从Java代码编译成.class文件, 之后实际就和Servlet没区别了, 也 ...

  8. WPF依赖属性对内存的使用方式

    WPF允许对象在创建时候并不包含存储数据的空间,只保留在用到时获取数据默认值,借用其他对象数据或者实时分配空间的能力

  9. WPF BorderBrush BorderThickness

    基本上所有的控件都可以设置BorderBrush BorderThickness 例如TextBox,Button

  10. 在WPF中,如何得到任何Object对象的XAML代码?

    原文:在WPF中,如何得到任何Object对象的XAML代码? 在WPF中,可以使用System.Windows.Markup.XamlWriter.Save(objName)得到任何Object对象 ...