目錄:
Java NIO 學習筆記(一)----概述,Channel/Buffer
Java NIO 學習筆記(二)----彙集和分散,通道到通道
Java NIO 學習筆記(三)----Selector
Java NIO 學習筆記(四)----文件通道和網絡通道
Java NIO 學習筆記(五)----路徑、文件和管道 Path/Files/Pipe
Java NIO 學習筆記(六)----異步文件通道 AsynchronousFileChannel
Java NIO 學習筆記(七)----NIO/IO 的對比和總結html
在 Java 7 中,AsynchronousFileChannel 已添加到 Java NIO 中,它能夠異步讀取數據並將數據寫入文件。先說明,異步和阻塞/非阻塞沒有關係,下面簡單介紹一下相關概念:java
通常異步都是和非阻塞組合使用的。編程
經過其靜態方法 open() 建立 AsynchronousFileChannel ,下面是一個示例:網絡
Path path = Paths.get("D:\\test\\input.txt"); AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); // 做爲對比,普通的 FileChannel 是這樣打開的: RandomAccessFile aFile = new RandomAccessFile("D:\\test\\input.txt", "rw"); FileChannel inChannel = aFile.getChannel();
open() 方法的第一個參數是指向 AsynchronousFileChannel 要關聯的文件的 Path 實例。第二個參數是可選的,能夠是一個或多個打開選項,這些選項告訴 AsynchronousFileChannel 在底層文件上執行什麼操做。在這個例子中,咱們使用了 StandardOpenOption.READ,這意味着該文件將被打開以供閱讀。多線程
能夠經過兩種方式從 AsynchronousFileChannel 讀取數據,都是調用 read() 方法之一完成的。dom
Future<Integer> read(ByteBuffer dst, long position); <A> void read(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer,? super A> handler);
Future 是 Java 多線程方面的內容,後面我會再繼續學習多線程的知識,這裏先稍微瞭解,帶過。
首先這個 Futrue 類有什麼用?咱們知道多線程編程的時候,通常使用 Runable ,重寫 run() 方法,而後調用線程對象的 start() 方法,重點就在 run() 方法的返回值是 void ,那若是咱們須要線程執行完成後返回結果怎麼辦,Future 就能夠解決這個問題。異步
從 AsynchronousFileChannel 讀取數據的第一種方法是調用 read() 方法,該方法返回 Future :async
Future<Integer> operation = fileChannel.read(buffer, 0);
此版本的 read() 方法將 ByteBuffer 做爲第一個參數。 從 AsynchronousFileChannel 讀取的數據被讀入此 ByteBuffer ,第二個參數指定文件中要開始讀取的字節位置。ide
即便讀取操做還沒有完成,read() 方法也會當即返回,能夠經過調用 read() 方法返回的 Future 實例的 isDone() 方法來檢查讀取操做什麼時候完成。這是一個示例:函數
Path path = Paths.get("D:\\test\\input.txt"); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; Future<Integer> operation = channel.read(buffer, position); while (!operation.isDone()) ; buffer.flip(); System.out.println(new String(buffer.array()));
此示例建立一個 AsynchronousFileChannel ,而後建立一個 ByteBuffer ,它做爲參數傳遞給 read() 方法,而且位置爲 0 ,在調用 read() 以後,循環調用 Future 的 isDone() 方法直到返回 true。 固然,這不是一個很是有效的 CPU 使用,可是這裏須要等待讀取操做完成。讀取操做完成後,將數據讀入 ByteBuffer 並輸出。
從 AsynchronousFileChannel 讀取數據的第二種方法是調用以 CompletionHandler 做爲參數的 read() 方法版本,其第二個參數 position 可指定從什麼位置開始讀取。 如下是調用此 read() 方法的示例:
Path path = Paths.get("D:\\test\\input.txt"); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer attachment) { System.out.println("result: " + result); attachment.flip(); System.out.println(new String(attachment.array())); attachment.clear(); } @Override public void failed(Throwable exc, ByteBuffer attachment) { System.out.println("failed"); } });
一旦讀取操做完成,將調用 CompletionHandler 的 completed() 方法,completed() 方法的第一個參數是 Integer 類型,表示讀取了多少字節,attachment 對應 read() 方法的第三個參數。 在這個例子中也是 ByteBuffer,數據也被讀入其中。 能夠自由選擇要附加的對象。若是讀取操做失敗,則將調用 CompletionHandler 的 failed() 方法。
和讀取數據相似,也能夠經過 AsynchronousFileChannel 對象的 2 種方法寫入數據:
Future<Integer> write(ByteBuffer src, long position); <A> void write(ByteBuffer src, long position, A attachment, CompletionHandler<Integer,? super A> handler);
具體的操做請參考讀取數據,這裏不展開了。