异步文件通道Java NIO你需要了解多少,来看看这篇文章
在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你需要了解多少,来看看这篇文章的更多相关文章
- Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- 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 ...
- 再有人问你Java内存模型是什么,就把这篇文章发给他
前几天,发了一篇文章,介绍了一下JVM内存结构.Java内存模型以及Java对象模型之间的区别.有很多小伙伴反馈希望可以深入的讲解下每个知识点.Java内存模型,是这三个知识点当中最晦涩难懂的一个,而 ...
- 可能是把Java内存区域讲的最清楚的一篇文章
写在前面(常见面试题) 下面是面试官可能在“Java内存区域”知识点问你的问题,快拿出小本本记下来! 基本问题: 介绍下Java内存区域(运行时数据区). Java对象的创建过程(五步,建议能默写出来 ...
- [No0000187]可能是把Java内存区域讲的最清楚的一篇文章
写在前面(常见面试题) 基本问题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针 ...
- 可能是把 Java 内存区域讲的最清楚的一篇文章
出处: 可能是把 Java 内存区域讲的最清楚的一篇文章 Java 内存区域详解 写在前面 (常见面试题) 基本问题 拓展问题 一 概述 二 运行时数据区域 2.1 程序计数器 2.2 Java 虚 ...
- 这应该是把Java内存区域讲的最清楚的一篇文章
基本问题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针两种方式) 拓展问题: ...
- Java NIO 学习
Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...
- [转]Java NIO通俗易懂简明教程
Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.本系列教程将有助于你学习和理解Java NIO. Java NIO提供了与 ...
随机推荐
- java 面向对象(一):类与对象
1.面向对象学习的三条主线: * 1.Java类及类的成员:属性.方法.构造器:代码块.内部类 * * 2.面向对象的大特征:封装性.继承性.多态性.(抽象性) * * 3.其它关键字:this.su ...
- JavaScript 基础 学习 (二)
JavaScript 基础 学习 节点属性 每一个节点都有自己的特点 这个节点属性就记录着属于自己节点的特点 1. nodeType(以一个数字来表示这个节点类型) 语法:节点.nodeT ...
- 第一部分软件测试综述——软件测试背景【软件测试】(美)Ron Patton中文电子版
截取自:第一部分软件测试综述——软件测试背景[软件测试](美)Ron Patton中文电子版(有需要的可以关注我) 第一部分软件测试综述 对手的程序死掉叫崩溃.自己的程序死掉叫“身体不良反应(idio ...
- Hexo 踩坑:jquery 报错
今天玩了一下Hexo(一个基于node.js的静态博客框架),结果部署到服务器上后发现了一个报错. jquery未定义. jquery怎么会报错呢?一看是找不到链接上的文件. //ajax.googl ...
- Shell基本语法---处理海量数据的cut命令
cut命令 cut应用场景:通常对数据进行列的提取 语法:cut [选项] [file] -d #指定分割符 -f #指定截取区域 -c #以字符为单位进行分割 # 以':'为分隔符,截取出/etc/ ...
- VS code 的集成终端Integrated terminal 的颜色问题
其实是默认终端的配色问题在使用vs code时,运行代码时,控制台是这样子的,搞得我很难受 一块一块的 其实是默认终端的配色问题 默认终端一般是powershell,还可以是cmd,或者git bas ...
- 【requests库】七个主要方法
本文主要介绍requests库访问http的七个主要方法:get.head.post.put.patch.delete. requests.get()方法 get方法用于获取指定url的HTML网页, ...
- java实现单链表的增删改以及排序
使用java代码模拟单链表的增删改以及排序功能 代码如下: package com.seizedays.linked_list; public class SingleLinkedListDemo { ...
- LevelDB,你好~
LevelDB,你好~ 上篇文章初识:LevelDB介绍了啥是LevelDB,LevelDB有啥特性,以及Linux环境下编译,使用及调试方法. 这篇文章的话,算是LevelDB源码学习的开端吧,主要 ...
- LQB2013A02排它平方数
这个题方向其实还算好找,就是枚举嘛 (这是一个填空题,所以六个for嵌套也无所谓,因为毕竟emmmm,不看时间) 这里是判断的代码: 需要把数字转化成字符串 void i2s(int x,string ...