上一篇知道了Buffer的工作机制,以及FileChannel的简单用法,这一篇介绍下 Scatter&Gather

1.Scatter(分散)

用于描述在Channel中读取的数据分散在不同的Buffer里。

接着上一篇的例子(rua文件内容为123456789),改造下代码:


readFile = new RandomAccessFile("D:\\rua.txt", "r");
FileChannel readChannel = readFile.getChannel();
ByteBuffer first = ByteBuffer.allocate(2); //第一块buffer
ByteBuffer second = ByteBuffer.allocate(2); //第二块buffer
ByteBuffer[] byteBuffers = {first, second};
long bytesRead = readChannel.read(byteBuffers); //从通道里读取数据到Buffer内(最大不超过Buffer容积)
while (bytesRead != -1) { //当读不到任何东西时返回-1
System.out.println("\nheader里的数据------此时byteRead=" + bytesRead);
first.flip(); //切换到Buffer读模式,读模式下可以读取到之前写入Buffer的数据
while (first.hasRemaining()) {
System.out.print("-" + (char) first.get()); //第一块Buffer读出的数据用减号分割,用于跟第二块区分
}
first.clear();
System.out.println("\nbody里的数据------此时byteRead=" + bytesRead);
second.flip();
while (second.hasRemaining()) {
System.out.print("+" + (char) second.get()); //第二块Buffer读出的数据用加号分割,用于跟第一块区分
}
second.clear(); // 切换回Buffer的写模式
System.out.println("\n----------------------------------------------");
bytesRead = readChannel.read(byteBuffers); //跟上面一样,再次从通道读取数据到Buffer中
}
System.out.print("\n-----------程序结束");

上面的代码开了两个Buffer,然后传给了Channel.read一个Buffer数组,运行结果如下:


header里的数据------此时byteRead=4
-1-2
body里的数据------此时byteRead=4
+3+4
---------------------------------------------- header里的数据------此时byteRead=4
-5-6
body里的数据------此时byteRead=4
+7+8
---------------------------------------------- header里的数据------此时byteRead=1
-9
body里的数据------此时byteRead=1 ---------------------------------------------- -----------程序结束

可以看到,文件里的内容被分段加载出来了,first buffer里首选读取一段,然后接着second buffer再接着读取接下来的一段。上面例子符合Scatter的描述。

看过网上一些文章,说的最多的例子就是协议头数据体分开处理的例子:

假设通过Channel获取到的数据存在固定长度的协议头,以及已知最大长度限制的数据体,就可以通过两个Buffer来接收,一个是header buffer,一个是body buffer,

但这个对数据要求很严苛,结合上面的例子,不难发现,想要做到准确无误的处理这个例子,就得要求事先必须知道header的长度,以及数据体的最大长度上限,为什么要这样呢?因为如果不知道header的长度,那么header buffer就可能会读到body buffer里的东西或者body buffer里读到header buffer里的东西,如果不知道body的上限长度,那么如果body数据长度超过了body buffer的长度,body里的数据就会再次读到header buffer中去(这个可以结合上面的例子理解)。

2.Gather(聚集)

用于描述在将不同Buffer里的数据写到同一个Channel中去。

来看个例子:


readFile = new RandomAccessFile("D:\\haha.txt", "rw");
FileChannel channel = readFile.getChannel();
ByteBuffer first = ByteBuffer.allocate(5); //第一块buffer
ByteBuffer second = ByteBuffer.allocate(5); //第二块buffer
first.put("aa".getBytes());
second.put("bb".getBytes());
first.flip();
second.flip();
ByteBuffer[] byteBuffers = {first, second};
channel.write(byteBuffers);
System.out.print("\n-----------程序结束");

运行结束后,haha.txt里的内容为:


aabb

可以看到,最终写入的数据就是按照顺序把两个buffer里的内容传输进去了。

同样的,还是以网上的协议头数据体的例子说事儿,这个跟Scatter下的传输方式比较起来就不会那么严格了,看到上面,初始容积为5个字节,但实际写到文件里的每个buffer仍然是两个字节,因为Gather模式下,Channel读取Buffer数据的时候,只会读取position到limit间的数据(可读区域),因此这里不用像多Buffer读一样要求那么严格,我们可以随意定义header buffer的长度,只要大于协议头本身长度即可,body buffer的要求其实是同上,也是大于数据体的长度上限即可。

这就是Scatter和Gather的全部内容了~其实简单理解,就是多Buffer操作,以及对网上那个例子,进行了更详细一点的说明。

Java NIO学习与记录(三): Scatter&Gather介绍及使用的更多相关文章

  1. Java NIO学习与记录(八): Reactor两种多线程模型的实现

    Reactor两种多线程模型的实现 注:本篇文章例子基于上一篇进行:Java NIO学习与记录(七): Reactor单线程模型的实现 紧接着上篇Reactor单线程模型的例子来,假设Handler的 ...

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

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

  3. Java NIO学习与记录(五): 操作系统的I/O模型

    操作系统的I/O模型 在开始介绍NIO Reactor模式之前,先来介绍下操作系统的五种I/O模型,了解了这些模型,对理解java nio会有不小的帮助. 先来看下一个服务端处理一次网络请求的流程图: ...

  4. Java NIO学习与记录(二):FileChannel与Buffer用法与说明

    FileChannel与Buffer用法与说明 上一篇简单介绍了NIO,这一篇将介绍FileChannel结合Buffer的用法,主要介绍Buffer FileChannel的简单使用&Buf ...

  5. Java NIO学习与记录(七): Reactor单线程模型的实现

    Reactor单线程模型的实现 一.Selector&Channel 写这个模型需要提前了解Selector以及Channel,之前记录过FileChannel,除此之外还有以下几种Chann ...

  6. Java NIO学习与记录(六): NIO线程模型

    NIO线程模型 上一篇说的是基于操作系统的IO处理模型,那么这一篇来介绍下服务器端基于IO模型和自身线程的处理方式. 一.传统阻塞IO模型下的线程处理模式 这种处理模型是基于阻塞IO进行的,上一篇讲过 ...

  7. Java NIO学习与记录(一):初识NIO

    初识 工作中有些地方用到了netty,netty是一个NIO框架,对于NIO却不是那么熟悉,这个系列的文章是我在学习NIO时的一个记录,也期待自己可以更好的掌握NIO. 一.NIO是什么? 非阻塞式I ...

  8. Java NIO学习与记录(四): SocketChannel与BIO服务器

    SocketChannel与BIO服务器 SocketChannel可以创建连接TCP服务的客户端,用于为服务发送数据,SocketChannel的写操作和连接操作在非阻塞模式下不会发生阻塞,这篇文章 ...

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

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

随机推荐

  1. asp.net core 1.1 mysqlsugarCore mysql.data 要 7.0.5.0

    Message=Could not load file or assembly 'MySql.Data, Version=7.0.5.0, Culture=neutral, PublicKeyToke ...

  2. csdn的blog可以直接导入内含图片的word文档吗?

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  3. Android 4.3实现类似iOS在音乐播放过程中如果有来电则音乐声音渐小铃声渐大的效果

    目前Android的实现是:有来电时,音乐声音直接停止,铃声直接直接使用设置的铃声音量进行铃声播放. Android 4.3实现类似iOS在音乐播放过程中如果有来电则音乐声音渐小铃声渐大的效果. 如果 ...

  4. B-spline Curves 学习前言与动机(1)

    B-spline Curves 学习之前言 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关的翻译学习. (原来博客网址:http:// ...

  5. 初尝2D骨骼动画编辑工具SPINE,并into Unity3D

    一.SPINE使用 研究2D骨骼动画,CYou的朋友介绍我SPINE这个工具,开发自Esoteric Software的一款专门制作2D动画的软件,网络上的资料还很少,我这从半吊子美术技术的角度简单说 ...

  6. lucene学习笔记(四)lucene分词详解

    分词器的核心类 Analyzer SimpleAnalyzer StopAnalyzer WhitespaceAnalyzer StandardAnalyzer TokenStream 分词器做好处理 ...

  7. [node.js]express+mongoose+mongodb的开发笔记

    时间过得很快,6月和7月忙的不可开交,糟心的事儿也是不少,杭州大连来回飞,也是呵呵. 希望下个阶段能沉浸下来,接着学自己想学的.记一下上几周用了几天时间写的课设.因为课设的缘故,所以在短时间里了解下e ...

  8. TypeScript白鹭引擎Egret防止按钮事件冒泡穿透

    this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, (event) => { if (event.target!=this) return;/ ...

  9. .Net Core Runtime安装说明

    在开发阶段,都是直接安装.Net Core的SDK,但是在部署的时候你还是直接装SDK吗?当然直接装SDK也没什么问题,也可以少一些麻烦.但是如果你像我一样不喜欢在产线上装SDK,只想装Runtime ...

  10. JS DOM对象控制HTML元素详解

    JS DOM对象控制HTML元素详解 方法: getElementsByName()  获取name getElementsByTagName()  获取元素 getAttribute()  获取元素 ...