您的位置:首页 > 编程语言 > Java开发

java NIO系列: Java NIO AsynchronousFileChannel

2016-06-27 00:55 771 查看

Java NIO AsynchronousFileChannel

Creating an AsynchronousFileChannel
Reading Data
Reading Data Via a Future
Reading Data Via a CompletionHandler
Writing Data
Writing Data Via a Future
Writing Data Via a CompletionHandler

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 an
AsynchronousFileChannel
:
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 the
AsynchronousFileChannel
 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 the
StandardOpenOption.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 the
read()
 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 a
Future
. 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 the
AsynchronousFileChannel
 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 Java
AsynchronousFileChannel
 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 the
AsynchronousFileChannel
 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 the
CompletionHandler
's methods.

original link: http://tutorials.jenkov.com/java-nio/asynchronousfilechannel.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: