目录:

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. qt的pos()和globalpos()(globalpos是相对于桌面的)

    参考:http://www.cppblog.com/izualzhy/archive/2011/03/21/142408.html 原文粘贴: 新建一个窗口程序,然后创建一个QMenu对象.在构造函数 ...

  2. [MVVM Light]Messenger 的使用

    原文:[MVVM Light]Messenger 的使用 当我们使用MVVM开发模式进行开发时,ViewModel之间的通信常常是很头疼的事情,好在MVVM Light提供了Messenger类可以轻 ...

  3. Python 产生两个方法将不被所述多个随机数的特定范围内反复

    在最近的实验中进行.通过随机切割一定比例所需要的数据这两个部分.事实上这个问题的核心是生成随机数的问题将不再重复.递归方法,首先想到的,然后我们发现Python中竟然已经提供了此方法的函数,能够直接使 ...

  4. Leetcode 169 Majority Element 分治

    在一个长度为n的数组中找出出现次数超过(n+1)/2次的数 说明请参考编程之美中的2.3 class Solution { public: int majorityElement(vector< ...

  5. JS 实现Map

    function Map() { this.arr = new Array(); var struct = function(key, value) { this.key = key; this.va ...

  6. Distinct去除重复项

    之前在做权限模块时,因不同角色可能拥有相同的菜单,导致呈现在浏览器上时出现重复菜单项,所以需要在获取用户拥有菜单项时需要过滤重复项, 用到了Distinct,两个重载 public static IQ ...

  7. Android发展_备份短信

     短信备份的原理 短信备份的原理.是用内容提供者读取短信,然后保存. public class SmsBackupUtils { // 回调接口 public interface SmsBacku ...

  8. 从零开始学习 asp.net core 2.1 web api 后端api基础框架(四)-创建Controller

    原文:从零开始学习 asp.net core 2.1 web api 后端api基础框架(四)-创建Controller 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog ...

  9. 第0001题 : 产生随机数(顺便读random模块官方文档)

    看这个之前我准备先看一下random模块的官方文档... 在整个随机模块中,  最基础的就是random, 它产生一个 [0.0, 1.0)的浮点数. 这个模块下所有的函数实际上是绑定在一个叫做ran ...

  10. Java Class SecurityManager

    # 前言 简单了解 SecurityManager.具体查阅 API. # What 它是 Java 沙盒模型控制安全的重要一个环节.它是 Java 的一个类.下面一段话源于SecurityManag ...