Java使用BIO和NIO進行檔案操作對比程式碼示例
阿新 • • 發佈:2020-05-14
什麼是Java NIO?
同步非阻塞io模式,拿燒開水來說,NIO的做法是叫一個執行緒不斷的輪詢每個水壺的狀態,看看是否有水壺的狀態發生了改變,從而進行下一步的操作。
Java NIO有三大組成部分:Buffer,Channel,Selector,通過事件驅動模式實現了什麼時候有資料可讀的問題。
什麼是Java BIO?
同步阻塞IO模式,資料的讀取寫入必須阻塞在一個執行緒內等待其完成。這裡使用那個經典的燒開水例子,這裡假設一個燒開水的場景,有一排水壺在燒開水,BIO的工作模式就是, 叫一個執行緒停留在一個水壺那,直到這個水壺燒開,才去處理下一個水壺。但是實際上執行緒在等待水壺燒開的時間段什麼都沒有做。不知道io操作中什麼時候有資料可讀,所以一直是阻塞的模式。
1、讀檔案
package com.zhi.test; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.file.Files; import java.nio.file.Paths; /** * 檔案讀取,緩衝區大小(BF_SIZE)對NIO的效能影響特別大,對BIO無影響<br> * 10M的檔案,BIO耗時87毫秒,NIO耗時68毫秒,Files.read耗時62毫秒 * * @author 張遠志 * @since 2020年5月9日19:20:49 * */ public class FileRead { /** * 緩衝區大小 */ private static final int BF_SIZE = 1024; /** * 使用BIO讀取檔案 * * @param fileName 待讀檔名 * @return * @throws IOException */ public static String bioRead(String fileName) throws IOException { long startTime = System.currentTimeMillis(); try { FileReader reader = new FileReader(fileName); StringBuffer buf = new StringBuffer(); char[] cbuf = new char[BF_SIZE]; while (reader.read(cbuf) != -1) { buf.append(cbuf); } reader.close(); return buf.toString(); } finally { System.out.println("使用BIO讀取檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } /** * 使用NIO讀取檔案 * * @param fileName 待讀檔名 * @return * @throws IOException */ public static String nioRead1(String fileName) throws IOException { long startTime = System.currentTimeMillis(); try { FileInputStream input = new FileInputStream(fileName); FileChannel channel = input.getChannel(); CharsetDecoder decoder = Charset.defaultCharset().newDecoder(); StringBuffer buf = new StringBuffer(); CharBuffer cBuf = CharBuffer.allocate(BF_SIZE); ByteBuffer bBuf = ByteBuffer.allocate(BF_SIZE); while (channel.read(bBuf) != -1) { bBuf.flip(); decoder.decode(bBuf,cBuf,false); // 解碼,byte轉char,最後一個引數非常關鍵 bBuf.clear(); buf.append(cBuf.array(),cBuf.position()); cBuf.compact(); // 壓縮 } input.close(); return buf.toString(); } finally { System.out.println("使用NIO讀取檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } /** * 使用Files.read讀取檔案 * * @param fileName 待讀檔名 * @return * @throws IOException */ public static String nioRead2(String fileName) throws IOException { long startTime = System.currentTimeMillis(); try { byte[] byt = Files.readAllBytes(Paths.get(fileName)); return new String(byt); } finally { System.out.println("使用Files.read讀取檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } public static void main(String[] args) throws IOException { String fileName = "E:/source.txt"; FileRead.bioRead(fileName); FileRead.nioRead1(fileName); FileRead.nioRead2(fileName); } }
2、寫檔案
package com.zhi.test; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.StandardOpenOption; /** * 檔案寫<br> * 10M的資料,BIO耗時45毫秒,NIO耗時42毫秒,Files.write耗時24毫秒 * * @author 張遠志 * @since 2020年5月9日21:04:40 * */ public class FileWrite { /** * 使用BIO進行檔案寫 * * @param fileName 檔名稱 * @param content 待寫記憶體 * @throws IOException */ public static void bioWrite(String fileName,String content) throws IOException { long startTime = System.currentTimeMillis(); try { FileWriter writer = new FileWriter(fileName); writer.write(content); writer.close(); } finally { System.out.println("使用BIO寫檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } /** * 使用NIO進行檔案寫 * * @param fileName 檔名稱 * @param content 待寫記憶體 * @throws IOException */ public static void nioWrite1(String fileName,String content) throws IOException { long startTime = System.currentTimeMillis(); try { FileOutputStream out = new FileOutputStream(fileName); FileChannel channel = out.getChannel(); ByteBuffer buf = ByteBuffer.wrap(content.getBytes()); channel.write(buf); out.close(); } finally { System.out.println("使用NIO寫檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } /** * 使用Files.write進行檔案寫 * * @param fileName 檔名稱 * @param content 待寫記憶體 * @throws IOException */ public static void nioWrite2(String fileName,String content) throws IOException { long startTime = System.currentTimeMillis(); try { File file = new File(fileName); if (!file.exists()) { file.createNewFile(); } Files.write(file.toPath(),content.getBytes(),StandardOpenOption.WRITE); } finally { System.out.println("使用Files.write寫檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } public static void main(String[] args) throws IOException { String content = FileRead.nioRead2("E:/source.txt"); String target1 = "E:/target1.txt",target2 = "E:/target2.txt",target3 = "E:/target3.txt"; FileWrite.bioWrite(target1,content); FileWrite.nioWrite1(target2,content); FileWrite.nioWrite2(target3,content); } }
3、複製檔案
package com.zhi.test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Paths; /** * 檔案複製<br> * 10M的檔案,bio耗時56毫秒,nio耗時12毫秒,Files.copy耗時10毫秒 * * @author 張遠志 * @since 2020年5月9日17:18:01 * */ public class FileCopy { /** * 使用BIO複製一個檔案 * * @param target 原始檔 * @param source 目標檔案 * * @throws IOException */ public static void bioCopy(String source,String target) throws IOException { long startTime = System.currentTimeMillis(); try { FileInputStream fin = new FileInputStream(source); FileOutputStream fout = new FileOutputStream(target); byte[] byt = new byte[1024]; while (fin.read(byt) > -1) { fout.write(byt); } fin.close(); fout.close(); } finally { System.out.println("使用BIO複製檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } /** * 使用NIO複製一個檔案 * * @param target 原始檔 * @param source 目標檔案 * * @throws IOException */ public static void nioCopy1(String source,String target) throws IOException { long startTime = System.currentTimeMillis(); try { FileInputStream fin = new FileInputStream(source); FileChannel inChannel = fin.getChannel(); FileOutputStream fout = new FileOutputStream(target); FileChannel outChannel = fout.getChannel(); inChannel.transferTo(0,inChannel.size(),outChannel); fin.close(); fout.close(); } finally { System.out.println("使用NIO複製檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } /** * 使用Files.copy複製一個檔案 * * @param target 原始檔 * @param source 目標檔案 * * @throws IOException */ public static void nioCopy2(String source,String target) throws IOException { long startTime = System.currentTimeMillis(); try { File file = new File(target); if (file.exists()) { file.delete(); } Files.copy(Paths.get(source),file.toPath()); } finally { System.out.println("使用Files.copy複製檔案耗時:" + (System.currentTimeMillis() - startTime) + "毫秒"); } } public static void main(String[] args) throws IOException { String source = "E:/source.txt"; String target1 = "E:/target1.txt",target3 = "E:/target3.txt"; FileCopy.bioCopy(source,target1); FileCopy.nioCopy1(source,target2); FileCopy.nioCopy2(source,target3); } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。