March 18, 2022

Write a File Asynchronously in Java

This post shows how to Write a file asynchronously in Java using the java.nio.channels.AsynchronousFileChannel class. Using AsynchronousFileChannel you can create an asynchronous file channel for reading, writing, and manipulating a file.

Writing file using AsynchronousFileChannel

Just like reading a file asynchronously, for asynchronous writing also there are two write methods-

  1. One of the write() method returns a Future instance representing the result of an asynchronous computation.
  2. In another write() method CompletionHandler instance is passed as an argument which consumes the result of an asynchronous I/O operation.

1. Java program to write file asynchronously

First we’ll use write method that returns Future instance.

Future<Integer> write(ByteBuffer src, long position)- Writes a sequence of bytes to this channel from the given buffer (represented by src), starting at the given file position. The method returns a Future representing the pending result of the write operation. The Future's get method returns the number of bytes written.

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 AsyncWrite {
  public static void main(String[] args) {
    // Path to the file for write operation
    Path path = Paths.get("F:\\knpcode\\Write.txt");
    // Create buffer acting as data source
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    // Data that has to be written
    buffer.put("This is test data".getBytes());
    // Reset current position to 0 and limit 
    // as current buffer position 
    buffer.flip();
    try(AsynchronousFileChannel asyncChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE)){
      // Write from buffer, start from position 0
      Future<Integer> future =  asyncChannel.write(buffer, 0);
      while(!future.isDone()) {
        System.out.println("Waiting for the asynchronous file write operation ..... ");
        System.out.println("Do some other processing");
      }   
      buffer.clear();
      
      System.out.println("Write operation done, bytes written- " + future.get());
    } catch (IOException | InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

2. Write file asynchronously using CompletionHandler

In this Java program to write file asynchronously we’ll use another write method that takes CompletionHandler as an argument.

public abstract <A> void write(ByteBuffer src, long position, A attachment, CompletionHandler<Integer,? super A> handler)- Writes a sequence of bytes to this channel from the given buffer, starting at the given file position.

java.nio.channels.CompletionHandler interface has two callback methods which you need to implement when using this write method.

  1. completed- This method is invoked when the I/O operation completes successfully.
  2. failed- This method is invoked if the I/O operations fails.
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 AsyncWrite {
  public static void main(String[] args) {
    // Path to the file for write operation
    Path path = Paths.get("F:\\knpcode\\Write.txt");
    // Create buffer acting as data source
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    // Data that has to be written
    buffer.put("This is test data".getBytes());
    // Reset current position to 0 and limit 
    // as current buffer position 
    buffer.flip();
    try(AsynchronousFileChannel asyncChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE)){
      // Write from buffer, start from position 0
      asyncChannel.write(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {

        @Override
        public void completed(Integer result, ByteBuffer attachment) {
          System.out.println("Write operation done, bytes written- " + result);
          attachment.clear();
        }

        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
          System.out.println("Write operation failed- " + exc.getMessage());					
        }
      });			
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Once the I/O operation finishes, completed() method is called. First argument of the completed() method is of type Integer specifying the number of bytes written. Type of the second argument “attachment” corresponds to the type of the third argument to the write() method, ByteBuffer in this case. Attachment specifies the buffer containing the content.

That's all for the topic Write a File Asynchronously in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment