Java使用BIO和NIO进行文件操作对比代码示例
作者:玄同太子 发布时间:2023-04-18 16:14:21
标签:Java,BIO,NIO,文件,操作
什么是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(), 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的数据,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", target2 = "E:/target2.txt", target3 = "E:/target3.txt";
FileCopy.bioCopy(source, target1);
FileCopy.nioCopy1(source, target2);
FileCopy.nioCopy2(source, target3);
}
}
来源:https://www.cnblogs.com/zhi-leaf/p/12860192.html


猜你喜欢
- 最近想关闭一个包的日志打印,经过一番研究实际上就一句话的事,一直没成功是因为name写错了。<logger name="pa
- 1.顺
- 现在很多Android应用在首次安装完都会有指引如何使用该应用的某些功能的指引界面,这样会获得很好的用户体验,能够帮助用户更好使用应用的某些
- 前言:小编引入的图片和文字描述都是来自于尚硅谷的视频讲解,在此感谢尚硅谷的老师,同时也结合 seata文档官方文档进行整合项目地址(gite
- 昨天写了一个关于Excel文件处理的脚本,在字符串匹配功能上总是出现多余不正确的匹配,debug调试之后,发现一个坑。------->
- Android IPC机制Messenger实例详解前言:Messenger可以翻译成信使,通过它可以在不同进程间传递Message对象有了
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- 静态变量初始化顺序1.简单规则首先先看一段最普遍的JAVA代码:public class Test{ public static Test1
- 缘起随着 App 的成长,我们难免会遇到以下这些需求:H5 跳原生界面Notification 点击调相关界面根据后台返回数据跳转界面,例如
- 使用场景当遇到需要临时修改的 bug,但当前正在开发的内容不能删掉,这个时候就需要把当前已经开发的代码另外保存下来(即保存现场),当把 bu
- 本文实例介绍的是Android的Tab控件,Tab控件可以达到分页的效果,让一个屏幕的内容尽量丰富,当然也会增加开发的复杂程度,在有必要的时
- 限流背景在早期的计算机领域,限流技术(time limiting)被用做控制网络接口收发通信数据的速率。可以用来优化性能,减少延迟和提高带宽
- 介绍责任链模式是一种行为型设计模式,其目的是将请求从一个对象传递到另一个对象,直到找到能够处理该请求的对象为止.再责任链模式中,每个对象都持
- 实例如下:public string unicodetogb(string text) { &nbs
- 前段时间,有个同事说“30000000000000000000000000000000000000000000000000000000000
- 这个是SpringBoot的Maven插件,主要用来打包的,通常打包成jar或者war文件。其中goal标签可以有5个值:repackage
- springboot返回文件流@GetMapping(value = "/file/{fileName}")public
- OverView今天在复习的时候,突然复习到我们的相机操作,但是对于相机操作,对于我来说比较复杂的是对于权限的操作。所有我们需要对我们的相机
- 主要从以下十几个方面对Hibernate做总结,包括Hibernate的检索方式,Hibernate中对象的状态,Hibernate的3种检
- Java 虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途,如图所示:程序计数器程序计数