package ar.com.javacuriosities.nio;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/*
* Como parte de NIO 2 se agrego al API Asynchronous IO lo cual permite realizar estas operaciones para Sockets y Files
*
* API:
* - Future Style: La operación inicia un IO y retorna un Future
* - Callback Style: Esperamos un evento por medio de un CompletionHandler
*
*/
public class Lesson05AsynchronousIO {
public static void main(String[] args) {
try {
readFileAsynchronous();
writeFileAsynchronous();
} catch (Exception e) {
// Log and Handle exception
e.printStackTrace();
}
}
private static void readFileAsynchronous() throws Exception {
Path path = Paths.get("message.txt");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;
// Podemos usar un Future para ejecutar la operación
Future<Integer> operation = channel.read(buffer, position);
// Esperamos que la operación termine, esto no es eficiente pero es una
// forma
while (!operation.isDone())
;
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
System.out.println(new String(data));
buffer.clear();
// Otra forma mas eficiente es usando un Callback
channel.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) {
}
});
// Esperamos un segundo para ver el resultado del callback porque sino nuestro programa puede terminar antes
TimeUnit.SECONDS.sleep(1);
}
private static void writeFileAsynchronous() throws Exception {
Path path = Paths.get("asynchronous.txt");
Files.deleteIfExists(path);
Files.createFile(path);
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;
buffer.put("Asynchronous message".getBytes());
buffer.flip();
Future<Integer> operation = channel.write(buffer, position);
buffer.clear();
while(!operation.isDone());
ByteBuffer bufferForHandler = ByteBuffer.allocate(1024);
bufferForHandler.put("Asynchronous message".getBytes());
bufferForHandler.flip();
channel.write(bufferForHandler, position, null, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
System.out.println("Bytes written: " + result);
}
@Override
public void failed(Throwable e, ByteBuffer attachment) {
System.out.println("Write failed");
e.printStackTrace();
}
});
// Esperamos un segundo para ver el resultado del callback porque sino nuestro programa puede terminar antes
TimeUnit.SECONDS.sleep(1);
}
}