Java使用BIO和NIO進(jìn)行文件操作對(duì)比代碼示例
什么是Java NIO?
同步非阻塞io模式,拿燒開(kāi)水來(lái)說(shuō),NIO的做法是叫一個(gè)線(xiàn)程不斷的輪詢(xún)每個(gè)水壺的狀態(tài),看看是否有水壺的狀態(tài)發(fā)生了改變,從而進(jìn)行下一步的操作。Java NIO有三大組成部分:Buffer,Channel,Selector,通過(guò)事件驅(qū)動(dòng)模式實(shí)現(xiàn)了什么時(shí)候有數(shù)據(jù)可讀的問(wèn)題。
什么是Java BIO?
同步阻塞IO模式,數(shù)據(jù)的讀取寫(xiě)入必須阻塞在一個(gè)線(xiàn)程內(nèi)等待其完成。這里使用那個(gè)經(jīng)典的燒開(kāi)水例子,這里假設(shè)一個(gè)燒開(kāi)水的場(chǎng)景,有一排水壺在燒開(kāi)水,BIO的工作模式就是, 叫一個(gè)線(xiàn)程停留在一個(gè)水壺那,直到這個(gè)水壺?zé)_(kāi),才去處理下一個(gè)水壺。但是實(shí)際上線(xiàn)程在等待水壺?zé)_(kāi)的時(shí)間段什么都沒(méi)有做。不知道io操作中什么時(shí)候有數(shù)據(jù)可讀,所以一直是阻塞的模式。
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;/** * 文件讀取,緩沖區(qū)大小(BF_SIZE)對(duì)NIO的性能影響特別大,對(duì)BIO無(wú)影響<br> * 10M的文件,BIO耗時(shí)87毫秒,NIO耗時(shí)68毫秒,F(xiàn)iles.read耗時(shí)62毫秒 * * @author 張遠(yuǎn)志 * @since 2020年5月9日19:20:49 * */public class FileRead { /** * 緩沖區(qū)大小 */ 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讀取文件耗時(shí):' + (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轉(zhuǎn)char,最后一個(gè)參數(shù)非常關(guān)鍵bBuf.clear();buf.append(cBuf.array(), 0, cBuf.position());cBuf.compact(); // 壓縮 } input.close(); return buf.toString(); } finally { System.out.println('使用NIO讀取文件耗時(shí):' + (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讀取文件耗時(shí):' + (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、寫(xiě)文件
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;/** * 文件寫(xiě)<br> * 10M的數(shù)據(jù),BIO耗時(shí)45毫秒,NIO耗時(shí)42毫秒,F(xiàn)iles.write耗時(shí)24毫秒 * * @author 張遠(yuǎn)志 * @since 2020年5月9日21:04:40 * */public class FileWrite { /** * 使用BIO進(jìn)行文件寫(xiě) * * @param fileName 文件名稱(chēng) * @param content 待寫(xiě)內(nèi)存 * @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寫(xiě)文件耗時(shí):' + (System.currentTimeMillis() - startTime) + '毫秒'); } } /** * 使用NIO進(jìn)行文件寫(xiě) * * @param fileName 文件名稱(chēng) * @param content 待寫(xiě)內(nèi)存 * @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寫(xiě)文件耗時(shí):' + (System.currentTimeMillis() - startTime) + '毫秒'); } } /** * 使用Files.write進(jìn)行文件寫(xiě) * * @param fileName 文件名稱(chēng) * @param content 待寫(xiě)內(nèi)存 * @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寫(xiě)文件耗時(shí):' + (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、復(fù)制文件
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;/** * 文件復(fù)制<br> * 10M的文件,bio耗時(shí)56毫秒,nio耗時(shí)12毫秒,F(xiàn)iles.copy耗時(shí)10毫秒 * * @author 張遠(yuǎn)志 * @since 2020年5月9日17:18:01 * */public class FileCopy { /** * 使用BIO復(fù)制一個(gè)文件 * * @param target 源文件 * @param source 目標(biāo)文件 * * @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復(fù)制文件耗時(shí):' + (System.currentTimeMillis() - startTime) + '毫秒'); } } /** * 使用NIO復(fù)制一個(gè)文件 * * @param target 源文件 * @param source 目標(biāo)文件 * * @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復(fù)制文件耗時(shí):' + (System.currentTimeMillis() - startTime) + '毫秒'); } } /** * 使用Files.copy復(fù)制一個(gè)文件 * * @param target 源文件 * @param source 目標(biāo)文件 * * @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復(fù)制文件耗時(shí):' + (System.currentTimeMillis() - startTime) + '毫秒'); } } public static void main(String[] args) throws IOException { String source = 'E:/source.txt'; String target1 = 'E:/target1.txt', target2 = 'E:/target2.txt', target3 = 'E:/target3.txt'; FileCopy.bioCopy(source, target1); FileCopy.nioCopy1(source, target2); FileCopy.nioCopy2(source, target3); }}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. 利用CSS3新特性創(chuàng)建透明邊框三角2. html清除浮動(dòng)的6種方法示例3. CSS3實(shí)例分享之多重背景的實(shí)現(xiàn)(Multiple backgrounds)4. vue實(shí)現(xiàn)將自己網(wǎng)站(h5鏈接)分享到微信中形成小卡片的超詳細(xì)教程5. 不要在HTML中濫用div6. 使用css實(shí)現(xiàn)全兼容tooltip提示框7. 詳解CSS偽元素的妙用單標(biāo)簽之美8. JavaScript數(shù)據(jù)類(lèi)型對(duì)函數(shù)式編程的影響示例解析9. CSS代碼檢查工具stylelint的使用方法詳解10. Vue3使用JSX的方法實(shí)例(筆記自用)
