Java 压缩20M文件从30秒到1秒的优化过程,还不相信?

来源:/p/
总结
参考文章
有一个需求需要将前端传过来的10张照片 , 然后后端进行处理以后压缩成一个压缩包通过网络流传输出去 。之前没有接触过用Java压缩文件的 , 所以就直接上网找了一个例子改了一下用了 , 改完以后也能使用 , 但是随着前端所传图片的大小越来越大的时候 , 耗费的时间也在急剧增加 , 最后测了一下压缩20M的文件竟然需要30秒的时间 。压缩文件的代码如下 。
【Java 压缩20M文件从30秒到1秒的优化过程,还不相信?】public static void zipFileNoBuffer() {File zipFile = new File(ZIP_FILE);try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile))) {//开始时间long beginTime = System.currentTimeMillis();for (int i = 0; i < 10; i++) {try (InputStream input = new FileInputStream(JPG_FILE)) {zipOut.putNextEntry(new ZipEntry(FILE_NAME + i));int temp = 0;while ((temp = input.read()) != -1) {zipOut.write(temp);}}}printInfo(beginTime);} catch (Exception e) {e.printStackTrace();}}
这里找了一张2M大小的图片 , 并且循环十次进行测试 。打印的结果如下 , 时间大概是30秒 。
fileSize:20Mconsum time:29599
第一次优化过程-从30秒到2秒
进行优化首先想到的是利用缓冲区。在中read()方法每次只读取一个字节 。源码中也有说明 。
/*** Reads a byte of data from this input stream. This method blocks* if no input is yet available.** @returnthe next byte of data, or -1 if the end of the*file is reached.* @exceptionIOExceptionif an I/O error occurs.*/public native int read() throws IOException;
这是一个调用本地方法与原生操作系统进行交互 , 从磁盘中读取数据 。每读取一个字节的数据就调用一次本地方法与操作系统交互 , 是非常耗时的 。例如我们现在有30000个字节的数据 , 如果使用那么就需要调用30000次的本地方法来获取这些数据 , 而如果使用缓冲区的话(这里假设初始的缓冲区大小足够放下30000字节的数据)那么只需要调用一次就行 。因为缓冲区在第一次调用read()方法的时候会直接从磁盘中将数据直接读取到内存中 。随后再一个字节一个字节的慢慢返回 。
内部封装了一个byte数组用于存放数据 , 默认大小是8192
优化过后的代码如下
public static void zipFileBuffer() {File zipFile = new File(ZIP_FILE);try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(zipOut)) {//开始时间long beginTime = System.currentTimeMillis();for (int i = 0; i < 10; i++) {try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(JPG_FILE))) {zipOut.putNextEntry(new ZipEntry(FILE_NAME + i));int temp = 0;while ((temp = bufferedInputStream.read()) != -1) {bufferedOutputStream.write(temp);}}}printInfo(beginTime);} catch (Exception e) {e.printStackTrace();}}
输出
------BufferfileSize:20Mconsum time:1808
可以看到相比较于第一次使用效率已经提升了许多了
第二次优化过程-从2秒到1秒

Java 压缩20M文件从30秒到1秒的优化过程,还不相信?

文章插图
使用缓冲区的话已经是满足了我的需求了 , 但是秉着学以致用的想法 , 就想着用NIO中知识进行优化一下 。
使用
为什么要用呢?因为在NIO中新出了和 。正是因为它们的结构更加符合操作系统执行I/O的方式 , 所以其速度相比较于传统IO而言速度有了显著的提高 。就像一个包含着煤矿的矿藏 , 而则是派送到矿藏的卡车 。也就是说我们与数据的交互都是与的交互 。