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); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Java使用ByteArrayOutputStream 和 ByteArrayInputStream 避免重复读取配置文
这篇文章主要介绍了Java使用ByteArrayOutputStream 和 ByteArrayInputStream 避免重复读取配置文件的方法,需要的朋友可以参考下2015-12-12Java属性文件操作之Properties与ResourceBundle详解
这篇文章主要介绍了Java属性文件操作之Properties与ResourceBundle详解,两个类都可以读取属性文件中以key/value形式存储的键值对,ResourceBundle读取属性文件时操作相对简单,需要的朋友可以参考下2023-11-11Java中EnumMap和EnumSet枚举操作类的简单使用详解
这篇文章主要介绍了Java中EnumMap和EnumSet枚举操作类的简单使用详解,EnumMap是Map接口的一种实现,专门用于枚举类型的键,所有枚举的键必须来自同一个枚举 EnumMap不允许键为空,允许值为空,需要的朋友可以参考下2023-11-11window 下 win10 jdk8安装与环境变量的配置过程
这篇文章主要介绍了window 下 win10 jdk8安装与环境变量的配置,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-08-08浅谈SpringBoot在使用测试的时候是否需要@RunWith
本文主要介绍了浅谈SpringBoot在使用测试的时候是否需要@RunWith,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2023-01-01
最新评论