天天看點

Java NIO原理及簡單拷貝實列Java NIO原理及使用

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原理及簡單拷貝實列Java NIO原理及使用

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

Java NIO原理及簡單拷貝實列Java NIO原理及使用

3、将緩沖區寫入輸出通道,先調用

flip()

,該方法flip緩存,limit設定到目前position位置,并且limit标記到4,然後position設定為0。

Java NIO原理及簡單拷貝實列Java NIO原理及使用

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

Java NIO原理及簡單拷貝實列Java NIO原理及使用

5、最後需要調用

clear()

方法,該方法清空緩存,position設定到0,limit設定到capacity。

Java NIO原理及簡單拷貝實列Java NIO原理及使用

代碼示範

junit測試

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

拷貝完成!