Java NIO AsynchronousFileChannel 异步读写文件

在Java 7中,AsynchronousFileChannel已添加到Java NIO。 AsynchronousFileChannel使异步读写文件成为可能。接下来将说明如何使用AsynchronousFileChannel。

 

1.创建一个AsynchronousFileChannel

可以通过其静态方法open()创建一个AsynchronousFileChannel:

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

 

open()方法的第一个参数是一个Path实例,该实例指向与AsynchronousFileChannel关联的文件。

第二个参数是一个或多个打开的选项,它们告诉AsynchronousFileChannel对基础文件执行哪些操作。在此示例中,我们使用了StandardOpenOption.READ,这意味着将打开文件进行读取。

 

2.读取数据

可以通过两种方式从AsynchronousFileChannel读取数据。

 

3.通过Future读取数据

从AsynchronousFileChannel读取数据的第一种方法是调用read()方法,该方法返回Future。

Future 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 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,然后创建一个ByteBuffer,将其作为参数传递给read()方法,位置设为0。在调用read()之后,该示例循环运行,直到返回的Future的isDone()方法返回true。当然,这不是对CPU的非常有效的使用-但是你需要以某种方式等待读取操作完成。

一旦读取操作完成,数据将被读取到ByteBuffer中,然后被读取到String中,并打印到System.out中。

 

4.通过CompletionHandler读取数据

从AsynchronousFileChannel读取数据的第二种方法是调用以CompletionHandler作为参数的read()方法版本。

fileChannel.read(buffer, position, buffer, new CompletionHandler() {
    @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的completed()方法。方法第一个参数表明多少字节被读,第二个参数是read读入数据的缓冲区。

如果读取操作失败,则将改为调用CompletionHandler的failed()方法。

 

5.写数据

就像读取一样,可以通过两种方式将数据写入AsynchronousFileChannel。

 

6.通过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 operation = fileChannel.write(buffer, position);
buffer.clear();

while(!operation.isDone());

System.out.println("Write done");

 

首先,以写入模式打开一个AsynchronousFileChannel。然后创建一个ByteBuffer并将一些数据写入其中。然后,将ByteBuffer中的数据写入文件。最后,该示例检查返回的Future以查看写入操作何时完成。

请注意,此代码生效之前,文件必须已经存在。如果文件不存在,则write()方法将抛出java.nio.file.NoSuchFileException。

你可以使用以下代码确保路径指向的文件存在:

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

 

7.通过CompletionHandler写入数据

还可以使用CompletionHandler将数据写入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() {

    @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()方法。

 

 

原文地址: https://www.zhblog.net/go/java/tutorial/java-nio-asynchronous-filechannel?t=630

 

 

你可能感兴趣的:(java,java,nio,Asynchronous,FileChannel)