舊IO(java.io.*)和新IO(java.nio.*)的主要區別,以下表:java
IO | NIO |
面向流 | 面向緩衝 |
阻塞IO | 非阻塞IO |
無 | 選擇器 |
java.nio.*是JDK1.4加入的。緩存
下面分別介紹:app
Java IO面向流意味着每次從流中讀一個或多個字節,直至讀取全部字節,它們沒有被緩存在任何地方。此外,它不能先後移動流中的數據。若是須要先後移動從流中讀取的數據,須要先將它緩存到一個緩衝區。函數
Java NIO的緩衝導向方法略有不一樣。數據讀取到一個它稍後處理的緩衝區,須要時可在緩衝區中先後移動。這就增長了處理過程當中的靈活性。可是,還須要檢查是否該緩衝區中包含全部您須要處理的數據。並且,需確保當更多的數據讀入緩衝區時,不要覆蓋緩衝區裏還沒有處理的數據。性能
Java IO的各類流是阻塞的。這意味着,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據徹底寫入。該線程在此期間不能再幹任何事情了。測試
Java NIO的非阻塞模式,如使一個線程從某通道發送請求讀取數據,可是它僅能獲得目前可用的數據,若是目前沒有數據可用時,就什麼都不會獲取。而不是保持線程阻塞,因此直至數據變的能夠讀取以前,該線程能夠繼續作其餘的事情。一個單獨的線程能夠管理多個輸入和輸出通道(channel)。ui
Java NIO的選擇器容許一個單獨的線程來監視多個輸入通道,你能夠註冊多個通道使用一個選擇器,而後使用一個單獨的線程來「選擇」通道:這些通道里已經有能夠處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。編碼
概念參考地址:http://ifeve.com/java-nio-vs-io/spa
在此,就拿最簡單的文件操做爲例,從一個文件讀數據並寫入另外一個文件,簡而言之就是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類,提供字符的編碼與解碼,方便實用。
暫時總結到這,再補充。如有錯誤,望糾正。