Java使用BIO和NIO進(jìn)行文件操作對比代碼示例
什么是Java NIO?
同步非阻塞io模式,拿燒開水來說,NIO的做法是叫一個線程不斷的輪詢每個水壺的狀態(tài),看看是否有水壺的狀態(tài)發(fā)生了改變,從而進(jìn)行下一步的操作。
Java NIO有三大組成部分:Buffer,Channel,Selector,通過事件驅(qū)動模式實現(xiàn)了什么時候有數(shù)據(jù)可讀的問題。
什么是Java BIO?
同步阻塞IO模式,數(shù)據(jù)的讀取寫入必須阻塞在一個線程內(nèi)等待其完成。這里使用那個經(jīng)典的燒開水例子,這里假設(shè)一個燒開水的場景,有一排水壺在燒開水,BIO的工作模式就是, 叫一個線程停留在一個水壺那,直到這個水壺?zé)_,才去處理下一個水壺。但是實際上線程在等待水壺?zé)_的時間段什么都沒有做。不知道io操作中什么時候有數(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)對NIO的性能影響特別大,對BIO無影響<br>
* 10M的文件,BIO耗時87毫秒,NIO耗時68毫秒,F(xiàn)iles.read耗時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讀取文件耗時:" + (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,最后一個參數(shù)非常關(guān)鍵
bBuf.clear();
buf.append(cBuf.array(), 0, 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的數(shù)據(jù),BIO耗時45毫秒,NIO耗時42毫秒,F(xiàn)iles.write耗時24毫秒
*
* @author 張遠(yuǎn)志
* @since 2020年5月9日21:04:40
*
*/
public class FileWrite {
/**
* 使用BIO進(jìn)行文件寫
*
* @param fileName 文件名稱
* @param content 待寫內(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寫文件耗時:" + (System.currentTimeMillis() - startTime) + "毫秒");
}
}
/**
* 使用NIO進(jìn)行文件寫
*
* @param fileName 文件名稱
* @param content 待寫內(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寫文件耗時:" + (System.currentTimeMillis() - startTime) + "毫秒");
}
}
/**
* 使用Files.write進(jìn)行文件寫
*
* @param fileName 文件名稱
* @param content 待寫內(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寫文件耗時:" + (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耗時56毫秒,nio耗時12毫秒,F(xiàn)iles.copy耗時10毫秒
*
* @author 張遠(yuǎn)志
* @since 2020年5月9日17:18:01
*
*/
public class FileCopy {
/**
* 使用BIO復(fù)制一個文件
*
* @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ù)制文件耗時:" + (System.currentTimeMillis() - startTime) + "毫秒");
}
}
/**
* 使用NIO復(fù)制一個文件
*
* @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ù)制文件耗時:" + (System.currentTimeMillis() - startTime) + "毫秒");
}
}
/**
* 使用Files.copy復(fù)制一個文件
*
* @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ù)制文件耗時:" + (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);
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ThreadPoolExecutor參數(shù)的用法及說明
這篇文章主要介紹了ThreadPoolExecutor參數(shù)的用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
mybatis如何實現(xiàn)in傳入數(shù)組查詢
這篇文章主要介紹了mybatis如何實現(xiàn)in傳入數(shù)組查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Java如何把數(shù)組轉(zhuǎn)換為ArrayList
這篇文章主要介紹了Java如何把數(shù)組轉(zhuǎn)換為ArrayList,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01
詳解 maven的pom.xml用<exclusion>解決版本問題
這篇文章主要介紹了詳解 maven的pom.xml用<exclusion>解決版本問題的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09
Java中instanceof關(guān)鍵字的用法總結(jié)
instanceof是Java的一個二元操作符,和==,>,<是同一類東東。由于它是由字母組成的,所以也是Java的保留關(guān)鍵字。它的作用是測試它左邊的對象是否是它右邊的類的實例,返回boolean類型的數(shù)據(jù)2013-10-10

