舊IO(java.io.*)和新IO(java.nio.*)的主要區別

 舊IO(java.io.*)和新IO(java.nio.*)的主要區別,以下表:java

IO NIO
面向流 面向緩衝
阻塞IO 非阻塞IO
選擇器

java.nio.*是JDK1.4加入的。緩存

下面分別介紹:app

1、面向流與面向緩衝

        Java IO面向流意味着每次從流中讀一個或多個字節,直至讀取全部字節,它們沒有被緩存在任何地方。此外,它不能先後移動流中的數據。若是須要先後移動從流中讀取的數據,須要先將它緩存到一個緩衝區。函數

        Java NIO的緩衝導向方法略有不一樣。數據讀取到一個它稍後處理的緩衝區,須要時可在緩衝區中先後移動。這就增長了處理過程當中的靈活性。可是,還須要檢查是否該緩衝區中包含全部您須要處理的數據。並且,需確保當更多的數據讀入緩衝區時,不要覆蓋緩衝區裏還沒有處理的數據。性能

2、阻塞與非阻塞

        Java IO的各類流是阻塞的。這意味着,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據徹底寫入。該線程在此期間不能再幹任何事情了。測試

        Java NIO的非阻塞模式,如使一個線程從某通道發送請求讀取數據,可是它僅能獲得目前可用的數據,若是目前沒有數據可用時,就什麼都不會獲取。而不是保持線程阻塞,因此直至數據變的能夠讀取以前,該線程能夠繼續作其餘的事情。一個單獨的線程能夠管理多個輸入和輸出通道(channel)。ui

3、選擇器(Selectors)

        Java NIO的選擇器容許一個單獨的線程來監視多個輸入通道,你能夠註冊多個通道使用一個選擇器,而後使用一個單獨的線程來「選擇」通道:這些通道里已經有能夠處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。編碼

概念參考地址:http://ifeve.com/java-nio-vs-io/spa

4、性能比較(冰山一角)

在此,就拿最簡單的文件操做爲例,從一個文件讀數據並寫入另外一個文件,簡而言之就是copy。代碼以下:線程

public class IOAndNIO {
	private static final String sourcePath = "C:/Users/Administrator/Desktop/123.txt";
	private static final String destPath = "test-nio.txt";

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			long atime = System.currentTimeMillis();
			//nio方式
			runWithNIO();
			long btime = System.currentTimeMillis();
			System.out.println("nio-time:"+(btime-atime));
			
			atime = System.currentTimeMillis();
			//傳統方式
			runWithIO();
			btime = System.currentTimeMillis();
			System.out.println("io-time:"+(btime-atime));
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	@SuppressWarnings("resource")
	public static void runWithNIO() throws IOException {
		final int BSIZE = 1024;
		FileChannel in = new FileInputStream(sourcePath).getChannel();
		FileChannel out = new FileOutputStream(destPath).getChannel();
		ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
		while (in.read(buffer) != -1) {
			buffer.flip(); // Prepare for writing
			out.write(buffer);
			buffer.clear(); // Prepare for reading
		}
	}

	public static void runWithIO() throws IOException {
		String file = "test-io.txt";
		BufferedReader in = new BufferedReader(new StringReader(read()));
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
		String s = "";
		while ((s = in.readLine()) != null)
			out.println(s);
		out.close();
	}
	// 讀文件
	public static String read() throws IOException {
		BufferedReader in = new BufferedReader(new FileReader(sourcePath));
		String str;
		StringBuilder sb = new StringBuilder();
		while ((str = in.readLine()) != null)
			sb.append(str + "\n");
		in.close();
		return sb.toString();
	}
}

在文件很小的時候看不出區別,因此將測試文件大小增長到2M,測試結果以下:

很明顯nio採用的緩衝器,大大提高了速度。

在上述代碼nio段中,調用了read()方法後,數據就會輸入到緩衝器,因此就必須調用緩衝器的flip()方法,告訴緩衝器即將會有讀取字節的操做,write()方法操做後,數據仍在緩衝器中,因此必需要調用clear()方法,對全部內部指針從新安排以便下一次read(),緩衝器接受數據。

除此方法外,還有一個更簡單的方法,即調用transferTo()函數,該函數容許一個通道(channel)和另外一個通道直接相連。

將runWithNIO()方法改成以下:

public static void runWithNIO() throws IOException {
		FileChannel in = new FileInputStream(sourcePath).getChannel();
		FileChannel out = new FileOutputStream(destPath).getChannel();
		in.transferTo(0, in.size(), out);
	}

 

除了以上區別,nio包下還提供了例如Charset類,提供字符的編碼與解碼,方便實用。

 

暫時總結到這,再補充。如有錯誤,望糾正。

相關文章
相關標籤/搜索