乐趣区

关于java:异步文件通道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、分布式缓存、数据结构等等。

退出移动版