How much do you need to know about asynchronous file channel Java NIO, take a look at this article

In Java 7, AsynchronousFileChannel was added to Java NIO. Use AsynchronousFileChannel to read and write file data asynchronously.

Create an AsynchronousFileChannel

We can create it using the static method open() provided by AsynchronousFileChannel. The sample code is as follows:

Path path = Paths.get("data/test.xml");
AsynchronousFileChannel fileChannel =
    AsynchronousFileChannel.open(path, StandardOpenOption.READ);

The first parameter is an object instance of PATH, which points to the file associated with the AsynchronousFileChannel.

The second parameter is one or more operation options, which determines what operation AsynchronousFileChannel will do to the target file. In the sample code, we used StandardOpenOption.READ, which indicates that we are going to read the target file.

Read data

AsynchronousFileChannel provides two ways to read data, both by calling its own read() method. Two methods will be introduced below.

The first way to use Futrue to read data is to call the read() method of AsynchronousFileChannel, which returns an object of type Future.

Future operation = fileChannelread(buffer, 0);

The first parameter is ByteBuffer. The data read from AsynchronousFileChannel is written into this ByteBuffer first.

The second parameter indicates the starting position of reading data from the file.

This read() method will return immediately, even if the entire reading process has not completely ended. We can use operation.isDone() to check whether the reading is complete. The operation here is an instance of the Future type returned by the read() method above. The following is a detailed code example:

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

The above program first creates an AsynchronousFileChannel object, and then calls its read() method to return a Future. The read() method requires two parameters, one is ByteBuffer, and the other is the starting position of reading the file. Then the isDone() method is called in a loop to check whether the reading process is complete, and the isDone() method will return true after completion. Although this allows the cpu to idle for a while, we should wait for the read operation to complete before proceeding to the subsequent steps.

Once the reading is complete, the data is stored in the ByteBuffer, and then the data is converted into a string and output.

Use CompletionHandler to read data

The second way to read data is to call another overloaded read() method of AsynchronousFileChannel, which requires a CompletionHandler as a parameter. The following is a code example:

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 is complete, the complete() method of the CompletionHandler will be called. Its first parameter is an Integer type, which represents the number of bytes read. The second parameter attachment is of type ByteBuffer and is used to store the read data. It is actually the third parameter of the read() method. In the current example, we use ByteBuffer to store data, but we can also use other types.

When the reading fails, the failed() method of CompletionHandler will be called.

Writing data is just like reading. We also have two ways to write data to AsynchronousFileChannel. We can call its two overloaded write() methods. We will introduce them separately below.

Use Future to read data

AsynchronousFileChannel也可以异步写入数据。下面是一个完整的写入示例:

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 instantiate an AsynchronousFileChannel in write mode, then create a ByteBuffer and write some data. Then write the data to the file. Finally, check the returned Future to see if the writing is complete.

Note that the write target file must be created in advance, if it does not exist, the writh() method will throw a java.nio.file.NoSuchFileException.

We can solve this problem in the following ways:

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

Use CompletionHandler to write data

We can also use CompletionHandler instead of Future to write data to AsynchronousFileChannel. This way we can more directly know whether the writing process is complete. The following is a sample program:

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

When the writing procedure is completed, the completed() method of the CompletionHandler will be called. On the contrary, if the writing fails, the failed() method will be called.

Pay attention to how the parameter attachmentnt of the CompletionHandler method is used.

At last

Reply to the data by private message to receive a summary of Java interview questions from a major manufacturer + Alibaba Taishan manual + a learning guide for knowledge points + a summary of Java core knowledge points in a 300-page pdf document!

The content of these materials are all the knowledge points that the interviewer must ask during the interview. The chapter includes many knowledge points, including basic knowledge, Java collections, JVM, multi-threaded concurrency, spring principles, microservices, Netty and RPC, Kafka , Diary, design pattern, Java algorithm, database, Zookeeper, distributed cache, data structure, etc. file

Guess you like

Origin blog.csdn.net/weixin_46577306/article/details/107825583