java NIO系列: Java NIO AsynchronousFileChannel

17 篇文章 0 订阅

Java NIO AsynchronousFileChannel

Jakob Jenkov
Last update: 2015-05-07

In Java 7 the AsynchronousFileChannel was added to Java NIO. The AsynchronousFileChannel makes it possible to read data from, and write data to files asynchronously. This tutorial will explain how to use the AsynchronousFileChannel.

Creating an AsynchronousFileChannel

You create an AsynchronousFileChannel via its static method open(). Here is an example of creating anAsynchronousFileChannel:

Path path = Paths.get("data/test.xml");

AsynchronousFileChannel fileChannel =
    AsynchronousFileChannel.open(path, StandardOpenOption.READ);

The first parameter to the open() method is a Path instance pointing to the file theAsynchronousFileChannel is to be associated with.

The second parameter is one or more open options which tell the AsynchronousFileChannel what operations is to be performed on the underlying file. In this example we used theStandardOpenOption.READ which means that the file will be opened for reading.

Reading Data

You can read data from an AsynchronousFileChannel in two ways. Each way to read data call one of theread() methods of the AsynchronousFileChannel. Both methods of reading data will be covered in the following sections.

Reading Data Via a Future

The first way to read data from an AsynchronousFileChannel is to call the read() method that returns aFuture. Here is how calling that read() method looks:

Future<Integer> operation = fileChannel.read(buffer, 0);

This version of the read() method takes ByteBuffer as first parameter. The data read from theAsynchronousFileChannel is read into this ByteBuffer. The second parameter is the byte position in the file to start reading from.

The read() method return immediately, even if the read operation has not finished. You can check the when the read operation is finished by calling the isDone() method of the Future instance returned by the read() method.

Here is a longer example showing how to use this version of the read() method:

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();

This example creates an AsynchronousFileChannel and then creates a ByteBuffer which is passed to the read() method as parameter, along with a position of 0. After calling read() the example loops until the isDone() method of the returned Future returns true. Of course, this is not a very efficient use of the CPU - but somehow you need to wait until the read operation has completed.

Once the read operation has completed the data read into the ByteBuffer and then into a String and printed to System.out .

Reading Data Via a CompletionHandler

The second method of reading data from an AsynchronousFileChannel is to call the read() method version that takes a CompletionHandler as a parameter. Here is how you call this read() method:

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) {

    }
});

Once the read operation finishes the CompletionHandler's completed() method will be called. As parameters to the completed() method are passed an Integer telling how many bytes were read, and the "attachment" which was passed to the read() method. The "attachment" is the third parameter to the read() method. In this case it was the ByteBuffer into which the data is also read. You can choose freely what object to attach.

If the read operation fails, the failed() method of the CompletionHandler will get called instead.

Writing Data

Just like with reading, you can write data to an AsynchronousFileChannel in two ways. Each way to write data call one of the write() methods of the AsynchronousFileChannel. Both methods of writing data will be covered in the following sections.

Writing Data Via a Future

The AsynchronousFileChannel also enables you to write data asynchronously. Here is a full JavaAsynchronousFileChannel write example:

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");

First an AsynchronousFileChannel is opened in write mode. Then a ByteBuffer is created and some data written into it. Then the data in the ByteBuffer is written to the file. Finally the example checks the returned Future to see when the write operation has completed.

Note, that the file must already exist before this code will work. If the file does not exist the write()method will throw a java.nio.file.NoSuchFileException .

You can make sure that the file the Path points to exists with the following code:

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

Writing Data Via a CompletionHandler

You can also write data to the AsynchronousFileChannel with a CompletionHandler to tell you when the write is complete instead of a Future. Here is an example of writing data to theAsynchronousFileChannel with a CompletionHandler:

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();
    }
});

The CompletionHandler's completed() method will get called when the write operation completes. If the write fails for some reason, the failed() method will get called instead.

Notice how the ByteBuffer is used as attachment - the object which is passed on to theCompletionHandler's methods.


original link: http://tutorials.jenkov.com/java-nio/asynchronousfilechannel.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值