Java NIO 学习笔记(二)----聚集和分散,通道到通道
目录:
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 学习笔记(二)----聚集和分散,通道到通道的更多相关文章
- JAVA NIO学习笔记二 频道和缓冲区
Java NIO 频道 Java NIO渠道类似于流,他们之间具有一些区别的: 您可以读取和写入频道.流通常是单向(读或写). 通道可以异步读取和写入数据. 通道常常是读取或写入缓冲区. 如上所述,您 ...
- Java NIO 学习笔记(七)----NIO/IO 的对比和总结
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(四)----文件通道和网络通道
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(三)----Selector
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO 学习笔记(一)----概述,Channel/Buffer
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO学习笔记
Java NIO学习笔记 一 基本概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执 ...
- Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer
作者:Grey 原文地址:Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer ByteBuffer.allocate()与ByteBuffer.allocateD ...
随机推荐
- WPF 导出资源文件
在wpf开发中我们可以把各种文件.图片打包到项目中也就是应用程序资源文件,然后在项目中可以通过特定的uri格式去调用.那有些时候为了方便我们可能想要在程序中将资源文件导出来使用,那么怎么做呢? 第 1 ...
- Oltu在Jersey框架上实现oauth2.0授权模块
oltu是一个开源的oauth2.0协议的实现,本人在此开源项目的基础上进行修改,实现一个自定义的oauth2.0模块. 关于oltu的使用大家可以看这里:http://oltu.apache.org ...
- COM编程基础(C++)
转自:http://www.yesky.com/20020715/1620482_1.shtml (作为一个初学者,觉得本文挺好,推荐给大家) 这篇文章是给初学者看的,尽量写得比较通俗易懂,并且尽量避 ...
- ORACLE 时间加减操作
DATE和timestamp类型都可以进行加减操作.可以对当前日期加年.月.日.时.分.秒,操作不同的时间类型,有三种方法: 1 使用内置函数numtodsinterval增加小时,分钟和秒2 加一个 ...
- 属性更改通知(INotifyPropertyChanged)——针对ObservableCollection
问题 在开发webform中,wpf中的ObservableCollection<T>,MSDN中说,在添加项,移除项时此集合通知控件,我们知道对一个集合的操作是CURD但是恰恰没有Upd ...
- Asp UserInfoList 方法二
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UserInfoList.a ...
- .Net Core 中使用PetaPoco ,T4生成模版
话不多说,直接上源码. 1.引用NuGet 2.添加T4 <#@ template debug="true" hostspecific="false" l ...
- 零元学Expression Blend 4 - Chapter 42 五分钟快速完成扇形变圆形动画
原文:零元学Expression Blend 4 - Chapter 42 五分钟快速完成扇形变圆形动画 零元学Expression Blend 4 - Chapter 42 五分钟快速完成扇形变圆形 ...
- C#高性能大容量SOCKET并发(五):粘包、分包、解包
原文:C#高性能大容量SOCKET并发(五):粘包.分包.解包 粘包 使用TCP长连接就会引入粘包的问题,粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一 ...
- 流程图浅析MFC架构
http://blog.csdn.net/qq2399431200/article/details/9035315