Java 7 AsynchronousFileChannel
is an asynchronous channel for reading and writing to files asynchronously. In this post, we will look into a few operations on AsynchronousFileChannel
.
- Read from a file using Future
- Read from File using CompletionHandler
- Write to File using Future
- Write to file using CompletionHandler
An AsynchronousFileChannel
can be created using the open method. This static method takes the Path
and the type of operations (READ, WRITE etc.) as paramters
Reading Data with Future
Following is the read()
method that returns a Future
.
Future operation = fileChannel.read(buffer, 0);
The data from the file is read into the ByteBuffer
parameter starting at the beginning of the file. Since this is an asynchronous call, the read()
method will return immediately, even if the read is not completed. To check if the read wheter the read operation completed, you can call the isDone()
on the returned Future
object.In the following program, we try to read from a file and wait till the read is complete. Although this is not an ideal use case, it will demonstrate how to use the "Read with Future" feature.
package nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class AsyncFileChannelTest {
public static void main(String[] args) {
Path path = Paths.get("C:/test/data.csv");
AsynchronousFileChannel fileChannel = null;
try {
fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;
StringBuffer fileData = new StringBuffer();
Future operation = fileChannel.read(buffer, position);
// Future returns -1 if End of File is reached.
while (operation.get() > 0) {
while (!operation.isDone())
;
// Switch ByteBuffer from read to write mode
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
fileData.append(new String(data));
buffer.clear();
// Update to new read position.
position = position + operation.get();
operation = fileChannel.read(buffer, position);
}
System.out.println(fileData);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reading with CompletionHandler
This version of the read()
operation takes a CompletionHandler
as a parameter.
package nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class AsyncFileChannelTest {
public static class MyCompletionHandler
implements CompletionHandler {
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
// TODO Auto-generated method stub
}
@Override
public void completed(Integer result, ByteBuffer buffer) {
System.out.println("result = " + result);
bytesRead = result.intValue();
if (bytesRead < 0)
return;
// Switch ByteBuffer from read to write mode
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
fileData.append(new String(data));
buffer.clear();
position = position + bytesRead;
fileChannel.read(buffer, position, buffer, this);
}
}
private static int bytesRead = 0;
private static StringBuffer fileData = new StringBuffer();
private static long position = 0;
private static AsynchronousFileChannel fileChannel = null;
public static void main(String[] args) {
Path path = Paths.get("C:/test/data.csv");
try {
fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
MyCompletionHandler myCompletionHandler = new MyCompletionHandler();
fileChannel.read(buffer, position, buffer, myCompletionHandler);
// read() returns -1 if End of File is reached.
while (bytesRead > 0) {
// Update to new read position.
position = position + bytesRead;
fileChannel.read(buffer, position, buffer, myCompletionHandler);
}
// Main thread waits till the asynchronous operations are complete
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(fileData);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Once the read is finished the completed()
method of CompletionHandler is called with the number of Bytes read as a paramter. The second parameter can be any object, and in our case, I passed the same ByteBuffer object as a parameter to help read the entire file. The failed()
method is called if the read operation fails.
Writing Data using Future
Writing to a file with Future
follows the same model as read. The differnces are that you open the channel in "WRITE" mode instead of "READ" and call the write()
method. When the write is done, the number bytes written to the file will be set in the Future
. As with read()
we wait till the read is complete by calling isDone()
method.
package nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class AsyncFileChannelTest {
public static void main(String[] args) {
Path path = Paths.get("C:/test/data.csv");
AsynchronousFileChannel fileChannel = null;
try {
fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
ByteBuffer buffer = ByteBuffer.allocate(100);
buffer.put("Hello World".getBytes());
buffer.flip();
Future operation = fileChannel.write(buffer, 0);
buffer.clear();
while(!operation.isDone());
System.out.println("Number of Bytes Written : " + operation.get());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
Writing with CompletionHandler
Writing to a file with CompletionHandler
follows the same model as a read. The differnces are that you open the channel in "WRITE" mode instead of "READ" and call the write()
method.
package nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class AsyncFileChannelTest {
public static class MyCompletionHandler implements CompletionHandler {
@Override
public void completed(Integer result, ByteBuffer attachment) {
System.out.println("Number of bytes written : " + result);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
// TODO Auto-generated method stub
}
}
public static void main(String[] args) {
Path path = Paths.get("C:/test/data.csv");
AsynchronousFileChannel fileChannel = null;
try {
fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
ByteBuffer buffer = ByteBuffer.allocate(100);
MyCompletionHandler myCompletionHandler = new MyCompletionHandler();
buffer.put("Hello World".getBytes());
buffer.flip();
fileChannel.write(buffer, 0, buffer, myCompletionHandler);
} catch (IOException e) {
e.printStackTrace();
}
// Main thread waits till the asynchronous operations are complete
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
No comments:
Post a Comment