zip压缩文件(二)

普通压缩文件以20M大小的文件为例

   public static void main(String[] args) {
        String source = "F:\\demo\\择天记 第5季 第01话 标清(270P).qlv";
        String zipFile = "F:\\demo\\zip\\择天记.zip";
        zipFileNoBuffer(zipFile, source);
    }

    public static void zipFileNoBuffer(String zipFilePath, String sourceFilePath) {
        try {
            File zipFile = new File(zipFilePath);
            File sourceFile = new File(sourceFilePath);
            long length = sourceFile.length();
            System.out.println("开始压缩文件、文件大小:[" + formetFileSize(length) + "] ...");
            long beginTime = System.currentTimeMillis();
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            InputStream input = new FileInputStream(sourceFile);
            zipOut.putNextEntry(new ZipEntry(sourceFile.getName()));
            int temp = 0;
            while ((temp = input.read()) != -1) {
                zipOut.write(temp);
            }
            input.close();
            zipOut.closeEntry();
            zipOut.close();
            //时间耗时
            System.out.println("压缩完毕,耗时:[" + printTimeConsuming(beginTime) + "] ms ...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

结果:

Connected to the target VM, address: '127.0.0.1:49281', transport: 'socket'
开始压缩文件、文件大小:[21.24M] ...
压缩完毕,耗时:[68652] ms ...
Disconnected from the target VM, address: '127.0.0.1:49281', transport: 'socket'

  

利用缓冲区BufferInputStream 优化

 1   private static void firstZipFile(String zipFilePath, String sourceFilePath){
 2         try {
 3             File zipFile = new File(zipFilePath);
 4             File sourceFile = new File(sourceFilePath);
 5             long length = sourceFile.length();
 6             System.out.println("开始压缩文件、文件大小:[" + formetFileSize(length) + "] ...");
 7             long beginTime = System.currentTimeMillis();
 8             FileOutputStream fileOut = new FileOutputStream(zipFile);
 9             ZipOutputStream zipOut = new ZipOutputStream(fileOut);
10             BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(zipOut);
11             InputStream input = new FileInputStream(sourceFile);
12             BufferedInputStream bufferedInputStream = new BufferedInputStream(input);
13             zipOut.putNextEntry(new ZipEntry(sourceFile.getName()));
14             int temp = 0;
15             while ((temp = bufferedInputStream.read()) != -1) {
16                 bufferedOutputStream.write(temp);
17             }
18             bufferedInputStream.close();
19             input.close();
20             bufferedOutputStream.close();
21             zipOut.close();
22             fileOut.close();
23             //时间耗时
24             System.out.println("压缩完毕,耗时:[" + printTimeConsuming(beginTime) + "] ms ...");
25         } catch (Exception e) {
26             e.printStackTrace();
27         }
28     }

结果:耗时缩短了(68652-2501)毫秒

Connected to the target VM, address: '127.0.0.1:51524', transport: 'socket'
开始压缩文件、文件大小:[21.24M] ...
压缩完毕,耗时:[2501] ms ...
Disconnected from the target VM, address: '127.0.0.1:51524', transport: 'socket'

 说明:

这是一个调用本地方法与原生操作系统进行交互,从磁盘中读取数据。每读取一个字节的数据就调用一次本地方法与操作系统交互,是非常耗时的。例如我们现在有30000个字节的数据,如果使用FileInputStream那么就需要调用30000次的本地方法来获取这些数据,而如果使用缓冲区的话(这里假设初始的缓冲区大小足够放下30000字节的数据)那么只需要调用一次就行。因为缓冲区在第一次调用read()方法的时候会直接从磁盘中将数据直接读取到内存中。随后再一个字节一个字节的慢慢返回。

第二次优化:

 1 /**
 2      * 第二次优化使用 Channel
 3      */
 4     private static void secondZipFile(String zipFilePath, String sourceFilePath ){
 5         try {
 6             File zipFile = new File(zipFilePath);
 7             File sourceFile = new File(sourceFilePath);
 8             long length = sourceFile.length();
 9             System.out.println("开始压缩文件、文件大小:[" + formetFileSize(length) + "] ...");
10             long beginTime = System.currentTimeMillis();
11             FileOutputStream fileOut = new FileOutputStream(zipFile);
12             ZipOutputStream zipOut = new ZipOutputStream(fileOut);
13             WritableByteChannel writableByteChannel = Channels.newChannel(zipOut);
14             FileInputStream input = new FileInputStream(sourceFile);
15             FileChannel channel =  input.getChannel();
16             zipOut.putNextEntry(new ZipEntry(sourceFile.getName()));
17             channel.transferTo(0, length, writableByteChannel);
18             channel.close();
19             input.close();
20             writableByteChannel.close();
21             zipOut.close();
22             fileOut.close();
23             //时间耗时
24             System.out.println("压缩完毕,耗时:[" + printTimeConsuming(beginTime) + "] ms ...");
25         } catch (Exception e) {
26             e.printStackTrace();
27         }
28     }

结果:比第一次优化耗时缩短了(2501-1810)毫秒

Connected to the target VM, address: '127.0.0.1:52021', transport: 'socket'
开始压缩文件、文件大小:[21.24M] ...
压缩完毕,耗时:[1810] ms ...
Disconnected from the target VM, address: '127.0.0.1:52021', transport: 'socket'

  

 

上一篇:xmake v2.5.2 发布, 支持自动拉取交叉工具链和依赖包集成


下一篇:Rust中语句和表达式的区别