目录:
Java NIO 学习笔记(一)----概述,Channel/Buffer
Java NIO 学习笔记(二)----汇集和分散,通道到通道
Java NIO 学习笔记(三)----Selector
Java NIO 学习笔记(四)----文件通道和网络通道
Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe
Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel
Java NIO 学习笔记(七)----NIO/IO 的对比和总结html
在 Java 7 中,AsynchronousFileChannel 已添加到 Java NIO 中,它能够异步读取数据并将数据写入文件。先说明,异步和阻塞/非阻塞没有关系,下面简单介绍一下相关概念:java
通常异步都是和非阻塞组合使用的。编程
经过其静态方法 open() 建立 AsynchronousFileChannel ,下面是一个示例:网络
Path path = Paths.get("D:\\test\\input.txt"); AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); // 做为对比,普通的 FileChannel 是这样打开的: RandomAccessFile aFile = new RandomAccessFile("D:\\test\\input.txt", "rw"); FileChannel inChannel = aFile.getChannel();
open() 方法的第一个参数是指向 AsynchronousFileChannel 要关联的文件的 Path 实例。第二个参数是可选的,能够是一个或多个打开选项,这些选项告诉 AsynchronousFileChannel 在底层文件上执行什么操做。在这个例子中,咱们使用了 StandardOpenOption.READ,这意味着该文件将被打开以供阅读。多线程
能够经过两种方式从 AsynchronousFileChannel 读取数据,都是调用 read() 方法之一完成的。dom
Future<Integer> read(ByteBuffer dst, long position); <A> void read(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer,? super A> handler);
Future 是 Java 多线程方面的内容,后面我会再继续学习多线程的知识,这里先稍微了解,带过。
首先这个 Futrue 类有什么用?咱们知道多线程编程的时候,通常使用 Runable ,重写 run() 方法,而后调用线程对象的 start() 方法,重点就在 run() 方法的返回值是 void ,那若是咱们须要线程执行完成后返回结果怎么办,Future 就能够解决这个问题。异步
从 AsynchronousFileChannel 读取数据的第一种方法是调用 read() 方法,该方法返回 Future :async
Future<Integer> operation = fileChannel.read(buffer, 0);
此版本的 read() 方法将 ByteBuffer 做为第一个参数。 从 AsynchronousFileChannel 读取的数据被读入此 ByteBuffer ,第二个参数指定文件中要开始读取的字节位置。ide
即便读取操做还没有完成,read() 方法也会当即返回,能够经过调用 read() 方法返回的 Future 实例的 isDone() 方法来检查读取操做什么时候完成。这是一个示例:函数
Path path = Paths.get("D:\\test\\input.txt"); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; Future<Integer> operation = channel.read(buffer, position); while (!operation.isDone()) ; buffer.flip(); System.out.println(new String(buffer.array()));
此示例建立一个 AsynchronousFileChannel ,而后建立一个 ByteBuffer ,它做为参数传递给 read() 方法,而且位置为 0 ,在调用 read() 以后,循环调用 Future 的 isDone() 方法直到返回 true。 固然,这不是一个很是有效的 CPU 使用,可是这里须要等待读取操做完成。读取操做完成后,将数据读入 ByteBuffer 并输出。
从 AsynchronousFileChannel 读取数据的第二种方法是调用以 CompletionHandler 做为参数的 read() 方法版本,其第二个参数 position 可指定从什么位置开始读取。 如下是调用此 read() 方法的示例:
Path path = Paths.get("D:\\test\\input.txt"); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer attachment) { System.out.println("result: " + result); attachment.flip(); System.out.println(new String(attachment.array())); attachment.clear(); } @Override public void failed(Throwable exc, ByteBuffer attachment) { System.out.println("failed"); } });
一旦读取操做完成,将调用 CompletionHandler 的 completed() 方法,completed() 方法的第一个参数是 Integer 类型,表示读取了多少字节,attachment 对应 read() 方法的第三个参数。 在这个例子中也是 ByteBuffer,数据也被读入其中。 能够自由选择要附加的对象。若是读取操做失败,则将调用 CompletionHandler 的 failed() 方法。
和读取数据相似,也能够经过 AsynchronousFileChannel 对象的 2 种方法写入数据:
Future<Integer> write(ByteBuffer src, long position); <A> void write(ByteBuffer src, long position, A attachment, CompletionHandler<Integer,? super A> handler);
具体的操做请参考读取数据,这里不展开了。