目录:

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. PV操作例题解析

    虽然自己看了书,老师讲了课,以为对PV操作理解了,可是遇到题的时候还是不会思考.以下这道题,花了非常长时间才弄明确,如今把思路写出来,大家共同探讨下. 大家都来思考: 信号量S1.S2.S3.S4分别 ...

  2. Wrapped的返回值取值

    Bared   Wrapped   using Newtonsoft.Json; using Newtonsoft.Json.Linq; string str = JsonConvert.Serial ...

  3. git 专题

    $ git pull origin test // git pull合并代码的时候,若发生冲突,会处于merging状态,检查代码,发现自己的分支低于主分支,这个时候想撤销merge // 撤销mer ...

  4. svn文件合并

     cd 目标目录svn merge -r 开始版本号:结束版本号 源目录或单个文件URL或svn merge 源目录或单个文件URL

  5. html send mail

    <html> <body> <script> var formattedBody = "FirstLine \n Second Line \n Third ...

  6. WPF svg 转 xmal

    原文:WPF svg 转 xmal 今天wpf里面要用矢量图,美工出的是svg格式的,需要将svg格式的转换为xaml 1.第一个尝试是安装Inkscape,这个软件可以直接将svg另存为xaml,但 ...

  7. Java中动态代理技术生成的类与原始类的区别 (good)

    用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...

  8. Visual Studio 2017报表RDLC设计器与工具箱中Report Viewer问题

    原文:VS2017入门 RDLC入门之01 本系列所有内容为网络收集转载,版权为原作者所有. VS2017初始安装后和VS2015一样,都没有ReportDesigner/ReportViewer R ...

  9. C#命名约定

    推荐的标识命名风格 风格名称 描述 使用建议 示例 Pascal大小写 标识符中每个单词都首字母大写 用于类型名和成员名 CarDeck, DealersHand Camel大小写 除第一个单词以外, ...

  10. Sql 2017 安装到sql_shared_mrconfigaction-install-confignonrc-cpu64卡住不动问题

    解决方法:取消功能选择的实例功能和共享功能中的"机器学习服务(数据库内)""机器学习服务器(独立)"