1. 程式人生 > >Java:全面 & 清晰的 NIO 學習攻略

Java:全面 & 清晰的 NIO 學習攻略

前言

  • JDK 1.4後,Java提供了一個全新的IO API,即 Java New IO
  • 本文 全面 & 詳細解析Java New IO,希望你們會喜歡

目錄

示意圖

儲備知識:Java IO

示意圖

1. 定義

  • Java New IO
  • 是1個全新的、 JDK 1.4後提供的 IO API

2. 作用

  • 提供了與標準IO不同的IO工作方式
  • 可替代 標準Java IOIO API

3. 新特性

對比於 Java IONIO具備的新特性如下

示意圖

4. 核心元件

Java NIO的核心元件 包括:

  • 通道(Channel
  • 緩衝區(Buffer
  • 選擇器(Selectors

下面將詳細介紹:

示意圖

5. 具體使用

5.1 基於通道 & 緩衝資料

具體步驟如下:

    // 1. 獲取資料來源 和 目標傳輸地的輸入輸出流(此處以資料來源 = 檔案為例)
    FileInputStream fin = new FileInputStream(infile);
    FileOutputStream fout = new FileOutputStream(outfile);

    // 2. 獲取資料來源的輸入輸出通道
    FileChannel fcin = fin.getChannel();
    FileChannel fcout = fout.getChannel();

    // 3. 建立 緩衝區 物件:Buffer(共有2種方法)
     // 方法1:使用allocate()靜態方法
     ByteBuffer buff = ByteBuffer.allocate(256);
     // 上述方法建立1個容量為256位元組的ByteBuffer
     // 注:若發現建立的緩衝區容量太小,則重新建立一個大小合適的緩衝區

    // 方法2:通過包裝一個已有的陣列來建立
     // 注:通過包裝的方法建立的緩衝區保留了被包裝陣列內儲存的資料
     ByteBuffer buff = ByteBuffer.wrap(byteArray);

     // 額外:若需將1個字串存入ByteBuffer,則如下
     String sendString="你好,伺服器. ";
     ByteBuffer sendBuff = ByteBuffer.wrap(sendString.getBytes("UTF-16"));

    // 4. 從通道讀取資料 & 寫入到緩衝區
    // 注:若 以讀取到該通道資料的末尾,則返回-1
    fcin.read(buff);

    // 5. 傳出資料準備:將快取區的寫模式 轉換->> 讀模式
    buff.flip();

    // 6. 從 Buffer 中讀取資料 & 傳出資料到通道
    fcout.write(buff);

    // 7. 重置緩衝區
    // 目的:重用現在的緩衝區,即 不必為了每次讀寫都建立新的緩衝區,在再次讀取之前要重置緩衝區
    // 注:不會改變緩衝區的資料,只是重置緩衝區的主要索引值
    buff.clear();

5.2 基於選擇器(Selecter)

具體步驟如下:

// 1. 建立Selector物件   
Selector sel = Selector.open();

// 2. 向Selector物件繫結通道   
 // a. 建立可選擇通道,並配置為非阻塞模式   
 ServerSocketChannel server = ServerSocketChannel.open();   
 server.configureBlocking(false);   
 
 // b. 繫結通道到指定埠   
 ServerSocket socket = server.socket();   
 InetSocketAddress address = new InetSocketAddress(port);   
 socket.bind(address);   
 
 // c. 向Selector中註冊感興趣的事件   
 server.register(sel, SelectionKey.OP_ACCEPT);    
 return sel;

// 3. 處理事件
try {    
    while(true) { 
        // 該呼叫會阻塞,直到至少有一個事件就緒、準備發生 
        selector.select(); 
        // 一旦上述方法返回,執行緒就可以處理這些事件
        Set<SelectionKey> keys = selector.selectedKeys(); 
        Iterator<SelectionKey> iter = keys.iterator(); 
        while (iter.hasNext()) { 
            SelectionKey key = (SelectionKey) iter.next(); 
            iter.remove(); 
            process(key); 
        }    
    }    
} catch (IOException e) {    
    e.printStackTrace();   
}

6. 例項講解

  • 例項說明:實現檔案複製功能
  • 實現方式:通道FileChannel、 緩衝區ByteBuffer
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {

    public static void main(String[] args) throws IOException {
        // 設定輸入源 & 輸出地 = 檔案
        String infile = "C:\\copy.sql";
        String outfile = "C:\\copy.txt";

        // 1. 獲取資料來源 和 目標傳輸地的輸入輸出流(此處以資料來源 = 檔案為例)
        FileInputStream fin = new FileInputStream(infile);
        FileOutputStream fout = new FileOutputStream(outfile);

        // 2. 獲取資料來源的輸入輸出通道
        FileChannel fcin = fin.getChannel();
        FileChannel fcout = fout.getChannel();

        // 3. 建立緩衝區物件
        ByteBuffer buff = ByteBuffer.allocate(1024);
        
        while (true) {

            // 4. 從通道讀取資料 & 寫入到緩衝區
            // 注:若 以讀取到該通道資料的末尾,則返回-1  
            int r = fcin.read(buff);
            if (r == -1) {
                break;
            }
            // 5. 傳出資料準備:呼叫flip()方法  
            buff.flip();
            
            // 6. 從 Buffer 中讀取資料 & 傳出資料到通道
            fcout.write(buff);
            
            // 7. 重置緩衝區
            buff.clear();
            
          }
        }

}

7. 與Java IO的區別

示意圖

8. 總結

  • 本文全面講解了Java中的NIO的相關知識
  • 下面我將繼續對 Android & Java中的知識進行深入講解 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記

請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!