十七、Java NIO AsynchronousFileChannel

所有文章

https://www.cnblogs.com/lay2017/p/12901123.html

正文

在Java7的时候,加入了AsynchronousFileChannel,使得你可以进行异步地read或write操作。本文关于如何使用AsynchronousFileChannel。

创建一个AsynchronousFileChannel

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

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

读取数据

读取数据有两种方式

通过Future读取

通过read获取Future,read方法会立即返回

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

下面是一个完整示例

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

示例中read直接返回了Future,通过Future不断轮询是否完成。完成以后,数据已经进入buffer。再从buffer读取数据并打印

通过CompletionHandler

除了通过Future主动轮询之外,还可以通过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) {

    }
});

我们看到,completed在正常回调的时候触发。failed回调在失败的时候触发

写入数据

与读取数据类似,写入数据同样支持两种方式

通过Future写入

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

写入数据要注意file必须存在,否则会抛出NoSuchFileException。你可以这样创建文件

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

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

和read类似,write正常结束会回调completed,失败回调failed。

原文地址:https://www.cnblogs.com/lay2017/p/12916545.html