目录:

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. (让你提前知道软件开发33):数据操纵语言(DML)

    文章2部分 数据库SQL语言 数据操纵语言(DML) 数据操纵语言(Data Manipulation Language,DML)包含insert.delete和update语句,用于增.删.改数据. ...

  2. XP双网卡不能上网的问题

    转载. 现在很多本本都是双网卡配置,让两个网卡分别负责连接内外网能够加快上网速度和连接稳定,但不少网友照做后会出现无法上网的情况,这是由于默认网关冲突所导致的.那么该如何处理让双网卡各行其是,互不干扰 ...

  3. C#.NET自定义报表数据打印

    原文:C#.NET自定义报表数据打印 这是一个自定义的报表打印,是对PrintPreviewDialog的扩展和封装.PrintPreviewDialog是一个windows的打印预览控件,该类返回的 ...

  4. XML Serialize/Deserialize

    using System; using System.Collections.Generic; using System.Globalization; using System.IO; using S ...

  5. MFC应用程序配置不正确解决方案(manifest对依赖的强文件名,WinSxs是windows XP以上版本提供的非托管并行缓存)

    [现象] 对这个问题的研究是起源于这么一个现象:当你用VC++2005(或者其它.NET)写程序后,在自己的计算机上能毫无问题地运行,但是当把此exe文件拷贝到别人电脑上时,便不能运行了,大致的错误提 ...

  6. 【shell】gerrit同步备份脚本的实现

    本期分享下gerrit如何实现备份,由于之前的一台代码服务器直接down掉,所以为了以防万一,开始备份gerrit数据,有人说,gerrit不过是个审查代码的工具,备份这个做什么,git是分布式代码管 ...

  7. Qt4可以使用trUtf8函数,其内容可以是中文,也可以是\F硬编码

    显示在textBrowser->setText 中文乱码 转成QObject::trUtf8即可. ui->textBrowser->setText((QObject::trUtf8 ...

  8. PySide——Python图形化界面入门教程(二)

    PySide——Python图形化界面入门教程(二) ——交互Widget和布局容器 ——Interactive Widgets and Layout Containers 翻译自:http://py ...

  9. fileapi.h里的API函数(包括LockFileEx和FindFirstChangeNotification函数)

    /** * This file is part of the mingw-w64 runtime package. * No warranty is given; refer to the file ...

  10. 《芒果TV》UWP版利用Windows10通用平台特性,率先支持Xbox One平台

    在Windows开发者中心开放提交Xbox平台应用之后,<芒果TV>UWP版迅速更新v3.1.2版,通过升级兼容目标,利用Windows10通用平台特性,率先覆盖Xbox平台用户. 芒果T ...