Java NIO原理及簡單拷貝實列

chetwhy發表於2019-04-19

Java NIO原理及使用

執行環境:idea2018,jdk11

簡述

1、比較

IO NIO
資料處理 位元組或字元流(stream) 塊(channel)
方向 單向(InputStream/OutputStream) 雙向(讀寫)

2、NIO(Non-blocking I/O),非阻塞IO,也可以理解為新IO(new I/O)。相對於傳統的IO以位元組或字元或單位傳輸,NIO以資料塊的方式批量傳輸。突出的有點就是快速和簡單,在網路傳輸中優勢明顯。

3、NIO具有雙向讀寫功能,支援一個快取中同時包含讀寫功能。

4、@since jdk1.4

通道Channel

NIO是在IO的基礎上整合出來的,而通道channel類似I/O中的流,通過它進行讀寫操作,且方向是雙向的。

通道在包java.nio.channels下,主要有以下4種型別

功能 channel for
FileChannel 從檔案中讀寫資料 reading, writing, mapping, and manipulating a file.
DatagramChannel 通過 UDP 讀寫網路中資料 datagram-oriented sockets.
SocketChannel 通過 TCP 讀寫網路中資料 stream-oriented connecting sockets
ServerSocketChannel 監聽新進來的TCP 連線 stream-oriented listening sockets

緩衝區

IO中緩衝充當裝飾類,非必須。而NIO中,一個通道的所有資料必須先放到緩衝區,再進行讀寫資料,不能直接操作通道進行讀寫。底層是一個陣列。

讀寫演示

1、為通道新建一個8個位元組緩衝區,則最大容量capacity為8,還可以讀寫的位元組數limit也為8,

指標posistion指向下一個待讀寫的位置,即當前已經讀寫的位元組數。

Java NIO原理及簡單拷貝實列

2、從輸入通道中讀取 4個位元組資料寫入緩衝區,posittion指標指向下一個位置4,limit不變。

Java NIO原理及簡單拷貝實列

3、將緩衝區寫入輸出通道,先呼叫flip(),該方法flip快取,limit設定到當前position位置,並且limit標記到4,然後position設定為0。

Java NIO原理及簡單拷貝實列

4、從緩衝區中取 4 個位元組到輸出緩衝中,此時 position 設為 4。

Java NIO原理及簡單拷貝實列

5、最後需要呼叫 clear() 方法,該方法清空快取,position設定到0,limit設定到capacity。

Java NIO原理及簡單拷貝實列

程式碼演示

使用nio,從d盤中的aaa.txt檔案拷貝到e盤。

public class TestNIO {

    @Test
    public void testCopy(){
        try {
            // 建立輸入流
            FileInputStream in = new FileInputStream("D:\\aaa.txt");
            // 建立輸入通道
            FileChannel inChannel = in.getChannel();
            // 建立輸出流
            FileOutputStream out = new FileOutputStream("E:\\aaa.txt");
            // 建立通道
            FileChannel outChannel = out.getChannel();
            // 建立快取,大小1024位元組
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
            // 迴圈讀寫
            while (true){
                // 從通道讀取序列的自接到給定緩衝區,更新position位置
                int read = inChannel.read(buffer);            
                // 全部讀完退出
                if (read==-1){
                    break;
                }   
                // flip快取,position回到0
                buffer.flip();
                // 緩衝區寫道輸出通道
                outChannel.write(buffer);
                // 清空,limit回到capacity
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
複製程式碼

拷貝完成!

相關文章