什么是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 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); } }