1. 程式人生 > >Java NIO (一)--簡介

Java NIO (一)--簡介

一、簡介


Java NIO (New IO)是JDK1.4後引入的新輸入/輸出API,提供基於緩衝區(buffer)的塊寫入/讀取,而以前的I/O是基於流(Stream)的方式,NIO基於塊的IO操作,將最耗時的快取區讀取和填充交由底層作業系統實現,因此速度上要快得多;主要由以下三個核心部分組成: 
1.Channel
2. Buffer 
3. Selector

二、Channel - 通道

通道可以理解為以前的“流”,資料從通道讀取,也可以向通道寫入資料,是雙向的,但是讀取和寫入都必須是使用Buffer,即讀取資料時,需要從通道讀取到快取區,然後再從緩衝區獲取資料,寫入資料也需要先將資料寫入到快取區,再將緩衝區寫入通道;

NIO中主要有以下通道型別: 
- FileChannel - 檔案IO 
- DatagramChannel - UDP傳輸 
- SocketChannel - TCP傳輸 
- ServerSocketChannel -TCP傳輸

三、Buffer - 緩衝區

緩衝區可以認為是一個數據容器,可以理解為一個基本資料型別陣列,如位元組陣列等;NIO中任何資料輸入/輸出都是必須經由緩衝區實現,主要有以下緩衝區型別: 
- ByteBuffer 
- CharBuffer 
- ShortBuffer 
- IntBuffer 
- LongBuffer 
- FloatBuffer 
- DoubleBuffer 
- MappedByteBuffer

可以看出以上型別覆蓋Java的全部基本型別,MappedByteBuffer(記憶體對映檔案,後續章節講解)對於每種Buffer都有相同的方法,只有ByteBuffer擁有部分特殊的方法

向Buffer中寫資料 

寫資料到Buffer有兩種方式: 

·        從Channel寫到Buffer。

·        通過Buffer的put()方法寫到Buffer裡。

從Channel寫到Buffer的例子 : 

int bytesRead = inChannel.read(buf); //read into buffer.
通過put方法寫Buffer的例子:
buf.put(127);  

從Buffer中讀取資料 

從Buffer中讀取資料有兩種方式: 

·        從Buffer讀取資料到Channel。

·       使用get()方法從Buffer中讀取資料。


從Buffer讀取資料到Channel的例子:

 //read from buffer into channel.  
 int bytesWritten = inChannel.write(buf);
使用get()方法從Buffer中讀取資料的例子 :
byte aByte = buf.get(); 

四、Selector - 選擇器

選擇器支援單個執行緒處理多個Channel,將多個Channel註冊到一個選擇器中,選擇器基於事件的方式處理;從選擇器獲取註冊Channel中關注的事件(如讀、寫)並進行資料處理,非常適用於多個數據量不大、讀寫不頻繁的通道,使用單個執行緒來處理;

五、NIO簡單(標準)的輸入/輸出

一個簡單(標準)的NIO輸入輸出一般包含如下步驟: 
1. 從資料來源獲取通道 
2. 分配緩衝區 
3. 切換快取區為寫模式 
4. 從通道讀取資料寫入緩衝區 
5. 切換緩衝區為讀模式 
6. 緩衝區資料寫入通道中 
7. 關閉資源

例項程式碼如下:

package com.denny.aio.test;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Test {

	public static void main(String[] args) throws IOException {
		
		RandomAccessFile formFile = new RandomAccessFile("src\\a.txt", "rw");
		RandomAccessFile toFile = new RandomAccessFile("src\\b.txt", "rw");
		
		//獲取channel
		FileChannel fromChannel = formFile.getChannel();
		FileChannel toChannel = toFile.getChannel();
		
		// 定義緩衝大小
		int bufSize = 1024*4;
		
		// 定義緩衝
		ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize);
		
		int len = 0;
		
		// 將資料從源channel寫入到緩衝區
		while(  (len=fromChannel.read(byteBuffer)) !=-1 ){
			
			//切換到讀模式
			byteBuffer.flip();
			
			//讀取緩衝區資料寫到目標channel
			toChannel.write(byteBuffer);
			
			// 清空緩衝
			byteBuffer.clear();
		}
		
		// 釋放資源
		toChannel.close();
		fromChannel.close();
	}
}