写点什么

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

用户头像
麦洛
关注
发布于: 2021 年 04 月 21 日

一. 7z rar zip 之间的区别

7z一般对应的软件是7zipzip对应的是winziprar对应的 winrar只不过现在这几个软件基本互相支持。7z压缩比率大些。zip次之,压缩比率越大,压缩的越小哦!!!
zip格式比较常见,支持泛围广。windows操作系统不装任选第三方软件也可以打开zip格式。rar 和7z必须用解压缩软件才行。
复制代码

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

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


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");    }
复制代码


我需要压缩的目录



压缩后的结果:


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();        }    }
复制代码


解压前:



解压后:


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

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



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 压缩

4.2 7zip 压缩


从结果来看,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 上面找到示例,自己动手测试

发布于: 2021 年 04 月 21 日阅读数: 11
用户头像

麦洛

关注

与其等待未来,不如创造未来 2020.04.10 加入

微信搜一搜"爱写Bug的麦洛" 公众号关注我,我们一起写bug

评论

发布
暂无评论
Zip和7-zip谁更强,如何选择?