Zip和7-zip谁更强,如何选择?

麦洛 等级 300 0 0

Zip和7-zip谁更强,如何选择?

一. 7z rar zip之间的区别

7z一般对应的软件是7zip
zip对应的是winzip
rar对应的 winrar
只不过现在这几个软件基本互相支持。
7z压缩比率大些。zip次之,压缩比率越大,压缩的越小哦!!!

zip格式比较常见,支持泛围广。windows操作系统不装任选第三方软件也可以打开zip格式。
rar 和7z必须用解压缩软件才行。

二 使用jdk操作winzip文件解压缩

我们使用jdk自带的zip解决方案来测试winzip文件解压缩

Zip和7-zip谁更强,如何选择?

2.1 压缩zip文件

    /**
     * 压缩zip文件
     * @param sourceFilePath
     * @param zipFilePath
     * @param fileName
     * @return
     */
    public static String zip(String sourceFilePath, String zipFilePath, String fileName) {
        File                sourceFile = new File(sourceFilePath);
        FileInputStream     fis;
        BufferedInputStream bis        = null;
        FileOutputStream    fos;
        ZipOutputStream     zos        = null;
        if (!sourceFile.exists()) {
            System.out.println("待压缩的文件目录:" + sourceFilePath + "不存在.");
        } else {
            try {
                File zipFile = new File(zipFilePath + File.separator + fileName + ".zip");
                if (zipFile.exists()) {
                    System.out.println(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");
                } else {
                    File[] sourceFiles = sourceFile.listFiles();
                    if (null == sourceFiles || sourceFiles.length < 1) {
                        System.out.println("待压缩的文件目录:" + sourceFilePath + "里面不存在文件,无需压缩.");
                    } else {
                        fos = new FileOutputStream(zipFile);
                        zos = new ZipOutputStream(new BufferedOutputStream(fos));
                        byte[] bufs = new byte[1024 * 10];
                        for (File file : sourceFiles) {
                            //创建ZIP实体,并添加进压缩包
                            ZipEntry zipEntry = new ZipEntry(file.getName());
                            zos.putNextEntry(zipEntry);
                            //读取待压缩的文件并写进压缩包里
                            fis = new FileInputStream(file);
                            bis = new BufferedInputStream(fis, 1024 * 10);
                            int read = 0;
                            while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
                                zos.write(bufs, 0, read);
                            }
                        }
                    }
                }
                return zipFile.getAbsolutePath();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } finally {
                //关闭流
                try {
                    if (null != bis) bis.close();
                    if (null != zos) zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

测试一下:

    public static void main(String[] args) {
        //压缩文件
        zip("E:\\excel", "E:\\excel", "excel");
    }

我需要压缩的目录 Zip和7-zip谁更强,如何选择?

压缩后的结果:

Zip和7-zip谁更强,如何选择?

2.2 解压zip文件

    /**
     * zip解压文件
     *
     * @param zipFilePath        压缩文件
     * @param unzipFilePath      解压文件路径
     * @param includeZipFileName 是否包含原文件名
     */
    public static String unZip(String zipFilePath, String unzipFilePath, boolean includeZipFileName) throws Exception {
        if (StringUtils.isBlank(zipFilePath) || StringUtils.isBlank(unzipFilePath)) {
            log.info("-> 必传参数为空");
            return null;
        }
        File zipFile = new File(zipFilePath);
        if (!zipFile.exists() || !zipFile.isFile()) {
            log.info("-> 要解压的文件不存在");
            return null;
        }
        log.info("-> 解压的文件大小: {}", zipFile.length());
        //如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径_
        if (includeZipFileName) {
            String fileName = zipFile.getName();
            log.info("-> fileName: {}", fileName);
            if (!fileName.isEmpty()) {
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
                log.info("-> fileName: {}", fileName);
            }
            unzipFilePath = unzipFilePath + File.separator + fileName;
        }
        log.info("-> unzipFilePath: {}", unzipFilePath);
        //创建解压缩文件保存的路径
        File unzipFileDir = new File(unzipFilePath);
        if (!unzipFileDir.exists() || !unzipFileDir.isDirectory()) {
            boolean crtDir = unzipFileDir.mkdirs();
            log.info("-> 创建存储解压后的路径{}", crtDir);
        }
        //开始解压
        ZipEntry                        entry;
        String                          entryFilePath, entryDirPath;
        File                            entryFile, entryDir;
        int                             index, count, bufferSize = 1024;
        byte[]                          buffer                   = new byte[bufferSize];
        BufferedInputStream             bis;
        BufferedOutputStream            bos;
        ZipFile                         zip                      = new ZipFile(zipFile, Charset.forName("gbk"));
        Enumeration<? extends ZipEntry> entries                  = zip.entries();
        //循环对压缩包里的每一个文件进行解压
        while (entries.hasMoreElements()) {
            entry = new ZipEntry(entries.nextElement());
            //构建压缩包中一个文件解压后保存的文件全路径
            entryFilePath = unzipFilePath + File.separator + entry.getName();
            fileFullNames.add(entryFilePath);
            entryDir = new File(entryFilePath);
            //如果文件夹路径不存在,则创建文件夹
            if (!(entryDir.exists() && entryDir.isDirectory())) {
                entryDir.mkdirs();
            }

            //创建解压文件
            entryFile = new File(entryFilePath);
            if (entryFile.exists()) {
                //删除已存在的目标文件
                entryFile.delete();
            }
            //写入文件
            bos = new BufferedOutputStream(new FileOutputStream(entryFile));
            bis = new BufferedInputStream(zip.getInputStream(entry));
            while ((count = bis.read(buffer, 0, bufferSize)) != -1) {
                bos.write(buffer, 0, count);
            }
            bos.flush();
            bos.close();

            bis.close();
        }
        return unzipFilePath;
    }

解压测试

    public static void main(String[] args) {
        //解压文件
        try {
            unZip("E:\\excel\\excel.zip", "E:\\excel\\jy", false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

解压前:

Zip和7-zip谁更强,如何选择?

解压后: Zip和7-zip谁更强,如何选择?

三 使用commons-compress操作7zip文件解压缩

这里,我们使用apache-commons-compress软件库来进行7zip文件的解压缩

Zip和7-zip谁更强,如何选择?

Apache Commons Compress库定义了一个用于处理ar,cpio,Unix转储,tar,zip,gzip,XZ,Pack200,bzip2、7z,arj,lzma,snappy,DEFLATE,lz4,Brotli,Zstandard,DEFLATE64和Z文件的API 。

此组件中的代码有很多渊源:

  • 对bzip2,tar和zip的支持来自Avalon的Excalibur,但就Apache的生存而言,其最初来自Ant。tar包最初是Tim Endres的公共领域包。bzip2软件包基于Keiron Liddle和Julian Seward的 libbzip2所做的工作。它已通过以下方式迁移: Ant-> Avalon-Excalibur-> Commons-IO-> Commons-Compress。
  • cpio软件包由Michael Kuss和jRPM 项目贡献。

3.1 maven依赖

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.9</version>
        </dependency>

3.2 压缩7zip文件

    /**
     * 7z文件压缩
     *
     * @param sourceFilePath  待压缩目录路径
     * @param zipFilePath 生成的压缩包路径
     * @param fileName 生成的压缩包目录
     */

    public static void compress7zip(String sourceFilePath, String zipFilePath, String fileName) throws Exception {
        File input = new File(sourceFilePath);
        if (!input.exists()) {
            throw new Exception(input.getPath() + "待压缩文件不存在");
        }
        SevenZOutputFile out = new SevenZOutputFile(new File(zipFilePath));

        compress(out, input, fileName);
        out.close();
    }

        /**
     * @param fileName 压缩文件名,可以写为null保持默认
     */
    //递归压缩
    public static void compress(SevenZOutputFile out, File input, String fileName) throws IOException {

        SevenZArchiveEntry entry = null;
        //如果路径为目录(文件夹)
        if (input.isDirectory()) {
            //取出文件夹中的文件(或子文件夹)
            File[] flist = input.listFiles();

            if (flist.length == 0)//如果文件夹为空,则只需在目的地.7z文件中写入一个目录进入
            {
                /*entry = out.createArchiveEntry(input,name + "/");
                out.putArchiveEntry(entry);*/
            } else//如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
            {
                for (int i = 0; i < flist.length; i++) {
                    compress(out, flist[i], fileName + "/" + flist[i].getName());
                }
            }
        } else//如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入7z文件中
        {
            FileInputStream fos = new FileInputStream(input);
            BufferedInputStream bis = new BufferedInputStream(fos);
            entry = out.createArchiveEntry(input, fileName);
            out.putArchiveEntry(entry);
            int len = -1;
            //将源文件写入到7z文件中
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1) {
                out.write(buf, 0, len);
            }
            bis.close();
            fos.close();
            out.closeArchiveEntry();
        }
    }

3.3 解压7zip文件

    /**
     * 7Zzip解压文件
     *
     * @param zipFilePath        压缩文件
     * @param unzipFilePath      解压文件路径
     * @param includeZipFileName 是否包含原文件名
     */
    public static String un7zZip(String zipFilePath, String unzipFilePath, boolean includeZipFileName) throws Exception {
        if (StringUtils.isBlank(zipFilePath) || StringUtils.isBlank(unzipFilePath)) {
            log.info("-> 必传参数为空");
            return null;
        }
        File zipFile = new File(zipFilePath);
        if (!zipFile.exists() || !zipFile.isFile()) {
            log.info("-> 要解压的文件不存在");
            return null;
        }
        log.info("-> 解压的文件大小: {}", zipFile.length());
        //如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径_
        if (includeZipFileName) {
            String fileName = zipFile.getName();
            log.info("-> fileName: {}", fileName);
            if (!fileName.isEmpty()) {
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
                log.info("-> fileName: {}", fileName);
            }
            unzipFilePath = unzipFilePath + File.separator + fileName;
        }
        log.info("-> unzipFilePath: {}", unzipFilePath);
        //创建解压缩文件保存的路径
        File unzipFileDir = new File(unzipFilePath);
        if (!unzipFileDir.exists() || !unzipFileDir.isDirectory()) {
            boolean crtDir = unzipFileDir.mkdirs();
            log.info("-> 创建存储解压后的路径{}", crtDir);
        }
        //开始解压
        String                          entryFilePath, entryDirPath;
        SevenZFile zIn = new SevenZFile(zipFile);
        SevenZArchiveEntry entry = null;
        File file = null;

        StringJoiner fileFullNames = new StringJoiner(",");
        while ((entry = zIn.getNextEntry()) != null) {
            if (!entry.isDirectory()) {
                //构建压缩包中一个文件解压后保存的文件全路径
                entryFilePath = unzipFilePath + File.separator + entry.getName();
                //日志
                fileFullNames.add(entryFilePath);


                file = new File(entryFilePath);
                if (!file.exists()) {
                    new File(file.getParent()).mkdirs();//创建此文件的上级目录
                }

                //写文件
                OutputStream out = new FileOutputStream(file);
                BufferedOutputStream bos = new BufferedOutputStream(out);
                int len = -1;
                byte[] buf = new byte[1024];
                while ((len = zIn.read(buf)) != -1) {
                    bos.write(buf, 0, len);
                }
                // 关流顺序,先打开的后关闭
                bos.close();
                out.close();
            }
        }
        log.info("-> 解压成功: {}", fileFullNames.toString());
        return unzipFilePath;
    }

四 zip和7zip压缩结果比对

4.1 zip压缩

Zip和7-zip谁更强,如何选择?

4.2 7zip压缩

Zip和7-zip谁更强,如何选择?

从结果来看,7z压缩方式压缩比更高,生成文件越小,感觉可能文件越大,效果越明显,如果只针对于我本次测试而言,我发现7z的压缩方式相对zip来说,速度慢很多,所以如果是小文件操作,还是推荐zip

五 Zip4j

这里推荐一款操作zip的明星库Zip4j,非常的方便好用,也是我同事推荐给我的!!!!

5.1 Zip4j介绍

Zip4j是用于zip文件或流的最全面的Java库。在撰写本文时,除其他一些功能外,它是唯一支持zip加密的Java库。它试图使处理zip文件/流变得更加容易。输入流和输出流不再笨拙的样板代码。正如你可以在下面的用法部分中看到,与zip文件的工作,现在即使是一个单一的代码行,比起这个。我的意思是不破坏Java的内置zip支持。实际上,该库依赖于Java的内置邮政编码,并且它本来应该更多。复杂如果我还必须编写压缩逻辑,那就很有挑战性。但老实说,使用zip文件或流可能是很多样板代码。该库的主要目的是通过在库中进行繁重的工作来为zip文件或流的所有常规操作提供一个简单的API,而不必让开发人员担心必须处理流等。

5.2 Zip4j特性

  • 创建,添加,提取,更新,从zip文件中删除文件
  • 支持流(ZipInputStream和ZipOutputStream)
  • 读/写受密码保护的zip文件和流
  • 支持AES和zip标准加密方法
  • 支持Zip64格式
  • 存储(无压缩)和放气压缩方法
  • 从拆分的zip文件创建或提取文件(例如:z01,z02,... zip)
  • 支持Unicode中的Unicode文件名和注释
  • 进度监视器-用于集成到应用程序和面向用户的应用程序中

5.3 功能演示

package com.milo.zip;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import org.junit.Test;

import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * @author Milo Lee
 * @date 2020-12-28 15:47
 */
public class ZipTest {

    /**
     *创建zip文件,包含单个文件
     */
    @Test
    public void test1(){
        try {
            //方式一
            new ZipFile("F:\\电子书\\milolee.zip").addFile("F:\\电子书\\Head First Java 中文高清版.pdf");
            //方式二
            new ZipFile("F:\\电子书\\milolee.zip").addFile(new File("F:\\电子书\\Head First Java 中文高清版.pdf"));
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建zip文件,包含多个文件
     */
    @Test
    public void test2(){
        try {
            new ZipFile("F:\\电子书\\milolee.zip").addFiles(Arrays.asList(new File("F:\\电子书\\Head First Java 中文高清版.pdf"),
                    new File("F:\\电子书\\Spring源码深度解析.pdf")));
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建受密码保护的zip文件
     */
    @Test
    public void test3(){
        ZipParameters zipParameters = new ZipParameters();
        zipParameters.setEncryptFiles(true);
        zipParameters.setEncryptionMethod(EncryptionMethod.AES);
        // Below line is optional. AES 256 is used by default. You can override it to use AES 128. AES 192 is supported only for extracting.
        zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);

        List<File> filesToAdd = Arrays.asList(
                new File("F:\\电子书\\Head First Java 中文高清版.pdf"),
                new File("F:\\电子书\\Spring源码深度解析.pdf")
        );

        ZipFile zipFile = new ZipFile("F:\\电子书\\milolee.zip", "milolee".toCharArray());
        try {
            zipFile.addFiles(filesToAdd, zipParameters);
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压zip
     */
    @Test
    public void test4(){
        try {
            new ZipFile("F:\\电子书\\milolee.zip").extractAll("F:\\电子书\\jy");
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压一个受密码保护的zip文件
     */
    @Test
    public void test5(){
        try {
            new ZipFile("F:\\电子书\\milolee.zip", "milolee".toCharArray()).extractAll("F:\\电子书\\jy");
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }
}

更多功能,大家可以在github上面找到示例,自己动手测试

收藏
评论区