在Java 7,AsynchronousFileChannel 被添加到了Java NIO中。使用AsynchronousFileChannel可以实现异步地读取和写入文件数据。

创建一个AsynchronousFileChannel

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

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

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

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

读取数据

AsynchronousFileChannel 提供了两种读取数据的方式,都是调用它本身的 read() 方法。下面将对两种方式进行介绍。

使用Futrue读取数据

第一种反式是调用 AsynchronousFileChannel 的 read() 方法,该方法反回一个 Future 类型的对象。

Future operation = fileChannelread(buffer, 0);

第一个参数是ByteBuffer,从 AsynchronousFileChannel 中读取的数据先写入这个 ByteBuffer 。

第二个参数表示从文件读取数据的开始位置。

此 read() 方法会立即返回,即使整个读的过程还没有完全结束。我们可以通过operation.isDone()来检查读取是否完成。这里的 operation 是上面调用 read() 方法返回的 Future 类型的实例。下面是一段详细的代码示例:

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,然后将数据转化为字符串既而输出。

使用CompletionHandler读取数据

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

fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public 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();
} @Override
public void failed(Throwable exc, ByteBuffer attachment) { }
});

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

读取失败的时候,CompletionHandler的 failed()方法会被调用。

写入数据

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

使用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。

我们可以用以下方式来解决这一问题:

if(!Files.exists(path)){
Files.createFile(path);
}

使用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>() { @Override
public void completed(Integer result, ByteBuffer attachment) {
System.out.println("bytes written: " + result);
} @Override
public void failed(Throwable exc, ByteBuffer attachment) {
System.out.println("Write failed");
exc.printStackTrace();
}
});

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

要留意CompletionHandler的方法的参数 attachemnt是怎么使用的。

最后

私信回复 资料 领取一线大厂Java面试题总结+阿里巴巴泰山手册+各知识点学习思维导+一份300页pdf文档的Java核心知识点总结!

这些资料的内容都是面试时面试官必问的知识点,篇章包括了很多知识点,其中包括了有基础知识、Java集合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。

异步文件通道Java NIO你需要了解多少,来看看这篇文章的更多相关文章

  1. Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel

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

  2. springcloud采坑--Zuul上传文件报java.nio.charset.IllegalCharsetNameException: UTF-8;boundary=sqgzzmMxl1UPdIp0IAYnQgUIAr9yNewVAzKIX

    报错日志: 2018-12-17 10:01:19,688 ERROR [io.undertow.request] (default task-3) UT005023: Exception handl ...

  3. 再有人问你Java内存模型是什么,就把这篇文章发给他

    前几天,发了一篇文章,介绍了一下JVM内存结构.Java内存模型以及Java对象模型之间的区别.有很多小伙伴反馈希望可以深入的讲解下每个知识点.Java内存模型,是这三个知识点当中最晦涩难懂的一个,而 ...

  4. 可能是把Java内存区域讲的最清楚的一篇文章

    写在前面(常见面试题) 下面是面试官可能在“Java内存区域”知识点问你的问题,快拿出小本本记下来! 基本问题: 介绍下Java内存区域(运行时数据区). Java对象的创建过程(五步,建议能默写出来 ...

  5. [No0000187]可能是把Java内存区域讲的最清楚的一篇文章

    写在前面(常见面试题) 基本问题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针 ...

  6. 可能是把 Java 内存区域讲的最清楚的一篇文章

    出处:  可能是把 Java 内存区域讲的最清楚的一篇文章 Java 内存区域详解 写在前面 (常见面试题) 基本问题 拓展问题 一 概述 二 运行时数据区域 2.1 程序计数器 2.2 Java 虚 ...

  7. 这应该是把Java内存区域讲的最清楚的一篇文章

    基本问题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针两种方式) 拓展问题: ...

  8. Java NIO 学习

    Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...

  9. [转]Java NIO通俗易懂简明教程

    Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.本系列教程将有助于你学习和理解Java NIO. Java NIO提供了与 ...

随机推荐

  1. Scala 基础(二):sbt介绍与构建Scala项目

    一.sbt简介 sbt是类似ANT.MAVEN的构建工具,全称为Simple build tool,是Scala事实上的标准构建工具. 主要特性: 原生支持编译Scala代码和与诸多Scala测试框架 ...

  2. web 部署专题(七):Ubuntu + Nginx + Flask + Gunicore环境搭建(服务器)

    现在我们手里有一个准备发布的项目,那么如何将他上传到你的服务器,并让外网访问呢? 安装: 安装Flask pip3 install flask 安装UWSGI pip3 install uwsgi 安 ...

  3. CMDB01 /paramiko模块、项目概述、项目架构、项目实现

    CMDB01 /paramiko模块.项目概述.项目架构.项目实现 目录 CMDB01 /paramiko模块.项目概述.项目架构.项目实现 1. paramiko 2. 基于xshell连接服务器 ...

  4. 集训作业 洛谷P3913 车的攻击

    这个题一开始被我想复杂了,但总体差不多. 脑子清醒后我直接看他占领了几条长,几条宽,比如一个长3宽3的地图. 被占领了一条宽,就可以看成一个长3宽2的地图.这个长3宽2的地图就是出去可以被攻击的点剩下 ...

  5. DEBUG ArrayList

    1,ArrayList面试必问 说说ArrayList和LinkedList的区别? ArrayList基于数组实现,LinkedList基于链表实现,不同的数据结构决定了ArrayList查询效率比 ...

  6. smartJQueryZoom(smartZoom) 的使用方法

    smartZoom 是一个我很喜欢用的库. 但是这个库有一些不完善的地方. 比如BUG. 比如使用上可能遇到的问题. <article> <div id="zoom_box ...

  7. Spring当中循环依赖很少有人讲,今天一起来学习!

    网上关于Spring循环依赖的博客太多了,有很多都分析的很深入,写的很用心,甚至还画了时序图.流程图帮助读者理解,我看了后,感觉自己是懂了,但是闭上眼睛,总觉得还没有完全理解,总觉得还有一两个坎过不去 ...

  8. 我们通常这样使用Linux弱口令检测!

    在Internet环境中,过于简单的口令是服务器面临的最大风险,对于管理员来说,即使找出这些弱口令账号是非常必要的,这样便于采取进一步的安全措施. 这里的话,弱口令检测需要用到一款密码破译软件--Jo ...

  9. python爬虫入门(4)----- selenium

    selenium 简介 selenium使用JavaScript模拟真实用户对浏览器进行操作.测试脚本执行时,浏览器自动按照脚本代码做出点击,输入,打开,验证等操作,就像真实用户所做的一样,从终端用户 ...

  10. DJANGO-天天生鲜项目从0到1-009-购物车-Ajax实现添加至购物车功能

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...