Java使用BIO和NIO进行文件操作对比代码示例

网友投稿 293 2022-12-07


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无影响

* 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;

/**

* 文件写

* 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;

/**

* 文件复制

* 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 outChannehttp://l = 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);

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java并发编程线程间通讯实现过程详解
下一篇:Java SimpleDateFormat线程安全问题原理详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~