1. 概述

Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。FileChannel无法设置为非阻塞模式,他总是运行在阻塞模式下。在Java 7中,AsynchronousFileChannel被添加到Java NIO。AsynchronousFileChannel使读取数据,并异步地将数据写入文件成为可能。

2. 创建一个AsynchronousFileChannel

使用AsynchronousFileChannel提供的静态方法 open() 创建它。示例代码如下:

Path path = Paths.get("data/test.xml");
AsynchronousFileChannel fileChannel =AsynchronousFileChannel.open(path, StandardOpenOption.READ);

第一个参数是一个 PATH 的对象实例,它指向了那个与 AsynchronousFileChannel 相关联的文件。

第二个参数是一个或多个操作选项,它决定了 AsynchronousFileChannel 将对目标文件做何种操作。示例代码中我们使用了 StandardOpenOption.READ ,它表明我们将要对目标文件进行读操作。

3. 从AsynchronousFileChannel中读取数据

3.1 使用Futrue读取数据

从AsynchronousFileChannel读取数据的第一种方法是调用返回Future的read()方法。下面是如何调用这个read()方法的示例:

Future<Integer> operation = fileChannel.read(buffer, 0);

read()方法的这个版本将ByteBuffer作为第一个参数。从AsynchronousFileChannel读取的数据被读入这个ByteBuffer。第二个参数是文件中的字节位置,以便开始读取。

read()方法会立即返回,即使读操作还没有完成。通过调用read()方法返回的Future实例的isDone()方法,您可以检查读取操作是否完成。

AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;Future<Integer> operation = fileChannel.read(buffer, position);while(!operation.isDone());buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
System.out.println(new String(data));
buffer.clear();

上面的程序首先创建了一个 AsynchronousFileChannel 对象,然后调用它的read()方法返回一个Future。其中read()方法需要两个参数,一个是ByteBuffer,另一个是读取文件的开始位置。然后通过循环调用isDone() 方法检测读取过程是否完成,完成后 isDone()方法将返回true。尽管这样让cpu空转了一会,但是我们还是应该等读取操作完成后再进行后续的步骤。

一旦读取完成,数据被存储到ByteBuffer,然后将数据转化为字符串既而输出。

3.2 使用CompletionHandler读取数据

第二种读取数据的方式是调用AsynchronousFileChannel 的另一个重载 read() 方法,改方法需要一个CompletionHandler 作为参数。下面是代码示例:

fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {System.out.println("result = " + result);attachment.flip();byte[] data = new byte[attachment.limit()];attachment.get(data);System.out.println(new String(data));attachment.clear();}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {}
});

一旦读取操作完成,CompletionHandler的 complete() 方法将会被调用。它的第一个参数是个 Integer类型,表示读取的字节数。第二个参数 attachment 是 ByteBuffer 类型的,用来存储读取的数据。它其实就是由 read() 方法的第三个参数。当前示例中,我们选用 ByteBuffer 来存储数据,其实我们也可以选用其他的类型。读取失败的时候,CompletionHandler的 failed()方法会被调用。

4. 向AsynchronousFileChannel中写入数据

就像读取一样,我们同样有两种方式向 AsynchronousFileChannel 写入数据。我们可以调用它的2个重载的 write() 方法。下面我们将分别加以介绍。

4.1 使用Future读取数据

AsynchronousFileChannel也可以异步写入数据。下面是一个完整的写入示例:

Path path = Paths.get("data/test-write.txt");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;buffer.put("test data".getBytes());
buffer.flip();Future<Integer> operation = fileChannel.write(buffer, position);
buffer.clear();while(!operation.isDone());System.out.println("Write done");

首先实例化一个写入模式的 AsynchronousFileChannel, 然后创建一个 ByteBuffer 并写入一些数据。再然后将数据写入文件。最后,检查返回的 Future,看是否写入完成。

注意,写入目标文件要提前创建好,如果它不存在的话,writh() 方法会抛出一个 java.nio.file.NoSuchFileException。

4.2 使用CompletionHandler写入数据

使用 CompletionHandler代替Future向AsynchronousFileChannel写入数据,这种方式可以更加直接的知道写入过程是否完成。下面是示例程序:

Path path = Paths.get("data/test-write.txt");
if(!Files.exists(path)){Files.createFile(path);
}
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;buffer.put("test data".getBytes());
buffer.flip();fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {System.out.println("bytes written: " + result);}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("Write failed");exc.printStackTrace();}
});

当写入程序完成时,CompletionHandler的completed()方法将会被调用,相反的如果写入失败则会调用failed()方法。

NIO详解(十二):AsynchronousFileChannel详解相关推荐

  1. 十二、详解计算网络中的流量控制和差错控制、HDLC

    十二.详解计算网络中的流量控制和差错控制 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动 ...

  2. 32.深度解密三十二:详解影响QQ群整体排名的那些秘密

    网络营销推广技术.技巧深度解密(三十二)指南: 1.本文档适合零基础以及互联网营销推广人员,主要讲解营销QQ群排名的一些问题. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. 3.敬畏法律 ...

  3. Linux内核Thermal框架详解十二、Thermal Governor(2)

    本文部分内容参考 万字长文 | Thermal框架源码剖析, Linux Thermal机制源码分析之框架概述_不捡风筝的玖伍贰柒的博客-CSDN博客, "热散由心静,凉生为室空" ...

  4. ViewPager 详解(二)---详解四大函数

    前言:上篇中我们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必须要重写的四个函数,它们都各有什么意义,在上节的函数内部为什么要这么实现,下面我们就结合Android的API说明 ...

  5. 攻防世界杂项(misc)--新手练习区(详解十二道题完结,附件做题过程中使用到的各种工具和网站)

    攻防世界杂项(misc)–新手练习区(详解) 第一题:this_is_flag 题目描述:Most flags are in the form flag{xxx}, for example:flag{ ...

  6. JavaScript 各种参数 详解(十二)

    程序代码 ' *---------------------------------------------------------------------------- ' * 函数:CheckIn ...

  7. 【接口测试基础】第十二篇 | 详解Postman测试报告

    Postman测试报告 安装newman(前提:确保npm-v验证通过) 1.安装newman时,必须保证node.js已经安装成功 2.在线安装命令: cnpm install -g newman ...

  8. 数字音频总线A2B开发详解十二(A2B一Master板做音效处理-31段EQ,高中低音分频等)

    作者的话 从板B上,我们把Master板上直通过来的音频信号,通过板子上的ADAU1761进行调音,可以让每一块从板都发出自己的声音,那么可不可以从源头,我们在Master上就把声音分配好,高音你去B ...

  9. element布局容器大小_Flutter完整开发实战详解(十六、详解自定义布局实战)

    本篇将解析 Flutter 中自定义布局的原理,并带你深入实战自定义布局的流程,利用两种自定义布局的实现方式,完成如下图所示的界面效果,看完这一篇你将可以更轻松的对 Flutter 为所欲为. 文章汇 ...

  10. 面渣逆袭:Redis连环五十二问,图文详解,这下面试稳了

    大家好,我是老三,面渣逆袭系列继续,这节我们来搞定Redis--不会有人假期玩去了吧?不会吧? 基础 1.说说什么是Redis? Redis是一种基于键值对(key-value)的NoSQL数据库. ...

最新文章

  1. 涉密计算机用户账号设置审批表,北京邮电大学涉密计算机配置审批表.PDF
  2. 大型门户网站架构设计的可伸缩性
  3. 原生JS实现图片滚动
  4. Nginx的405 not allowed错误解决
  5. Coolpad Y1刷机方法
  6. POJ2019(二维RMQ问题 ST)
  7. [JavaWeb-JavaScript]JavaScript运算符
  8. TCGA肿瘤基因数据的访问(二)
  9. 机器学习实战(MachineLearinginAction) 第二章 k-近邻算法
  10. Reactor模型-单线程版
  11. CSDN-markdown编辑器语法说明
  12. 特色租房管理系统/租房管理系统/房屋租赁管理系统
  13. GitHub的Fork 是什么意思?『举了个挺不错的例子,程序员Joe』
  14. linux迅雷命令行,Linux系统下使用wine运行迅雷5的方法
  15. 亚马逊qa是什么意思_“亚马逊成就”是什么意思?
  16. M3U8 Downloader的使用
  17. 经典100句——人生与社会
  18. 华硕服务器怎么装系统教程视频,华硕怎么安装linux系统教程视频
  19. IDEA代码提示快捷键Ctrl+Space不生效问题
  20. 共享经济:团队共享VS个体共享

热门文章

  1. cas单点登陆。就这一篇就够了!!!!!
  2. CCF - 201509-2 - 日期计算
  3. codeforces Round#429 (Div2)
  4. ClientDataSet 探讨
  5. Node.js 和Socket.IO 实现chat
  6. Dom Tree Node, Render Tree Node 结构
  7. 错误 SQL TOP子句中的行数必须是整数
  8. 算法周记(一)直接插入排序
  9. 偏心率e用于描述某一轨道与圆轨道的区别
  10. OpenCV的cv::cvtColor函数之“CV_RGB2GRAY”: 未声明的标识符错误解决方法