Java压缩和解压缩(四)7-Zip-Jbinding实践

Java压缩和解压缩
placeholder image
admin 发布于:2023-03-05 00:31:02
阅读:loading

1.基本介绍

7-Zip-jbinding是一个免费的跨平台java绑定7-Zip免费压缩/解压缩库,7z archiver引擎的Java包装器,内置了多个动态链接库文件来适配不同的操作系统,支持Linux、Windows、Mac,以及32/64位系统的支持,可实现应用的跨平台,支持多种压缩格式的文件,如:7zip、zip、gzip、rar(rar4和rar5)、tar、iso 等多种常见格式;支持压缩包文件的提取、分割卷的提、支持密码的压缩和解压缩、多线程等,对于程序的自动适配和兼容支持的比较友好。

7-Zip-JBinding 是一个c++版7-Zip的封装,由两部分组成:java部分和本机部分。java部分介绍了7-Zip库的跨平台java接口,7-Zip-jbinding的本机部分通过java jni接口与java部分通信,并使用相应的本机7-Zip接口进行操作,所以它的性能要比java.util.zip提供的API要高,官网也对应提供了一系列示例,可自行掌握了解,参考它的应用结构图为:

image.png

2.代码实现

package cn.chendd.compress;

import cn.chendd.compress.sevenz.CompressOutItemStructure;
import cn.chendd.compress.sevenz.Item;
import cn.chendd.compress.sevenz.SevenZCompressCallBack;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.IOutCreateArchive7z;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.impl.RandomAccessFileOutStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.List;

/**
 * @author chendd
 * @date 2023/3/5 19:20
 */
public class CompressRar {

    /**
     * 压缩文件(夹)
     * @param compressFile 压缩文件
     * @param sevenZipFile 压缩后的文件
     * @return 压缩的文件列表
     */
    public static List<File> sevenZ(File compressFile, File sevenZipFile) {
        return sevenZ(compressFile , sevenZipFile , null);
    }

    /**
     * 带密码的文件(夹)压缩
     * @param compressFile 压缩文件
     * @param sevenZipFile 压缩后的文件
     * @param password 密码
     * @return 压缩的文件列表
     */
    public static List<File> sevenZ(File compressFile, File sevenZipFile, String password) {
        //构建输出压缩对象
        IOutCreateArchive7z outArchive = null;
        RandomAccessFileOutStream outStream = null;
        List<File> resultList = Lists.newArrayList();
        try {
            outArchive = SevenZip.openOutArchive7z();
            if (! sevenZipFile.getParentFile().exists()) {
                sevenZipFile.getParentFile().mkdirs();
            }
            outStream = new RandomAccessFileOutStream(new RandomAccessFile(sevenZipFile, "rw"));
            List<Item> items = CompressOutItemStructure.create(compressFile);
            //压缩测试
            outArchive.setLevel(5);
            outArchive.setSolid(true);
            //设置加密文件名
            outArchive.setHeaderEncryption(true);
            //创建压缩对象
            outArchive.createArchive(outStream, items.size(), new SevenZCompressCallBack(compressFile, items , password));
            items.forEach(item -> {
                resultList.add(item.getFile());
            });
            return resultList;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (outStream != null) {
                try {
                    outStream.close();
                } catch (IOException ignore) {}
            }
            IOUtils.closeQuietly(outArchive);
        }
    }

    /**
     * 判断是否解压缩成功,判断标准:解压缩后的文件(夹)大于 解压前的文件
     * @param srcFile 源压缩包文件
     * @param destFile 解压缩后的文件
     * @return true 解压缩后的文件 大于 解压缩前的文件大小
     */
    public static boolean validatorUnSevenZ(File srcFile , File destFile) {
        return FileUtils.sizeOf(destFile) > srcFile.length();
    }

    /**
     * 解压缩
     * @param zipFile 压缩包文件
     * @param outFile 输出文件
     * @return 文件夹列表
     */
    public static List<File> unSevenZ(File zipFile , File outFile) {
        return unSevenZ(zipFile , outFile , null);
    }

    /**
     * 解压缩带密码文件
     * @param zipFile 压缩包文件
     * @param outFile 输出文件
     * @param password 密码
     * @return 文件列表
     */
    public static List<File> unSevenZ(File zipFile , File outFile , String password) {
        RandomAccessFileInStream inStream = null;
        IInArchive inArchive = null;
        boolean usePassword = StringUtils.isNotEmpty(password);
        List<File> resultList = Lists.newArrayList();
        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(zipFile, "r");
            inStream = new RandomAccessFileInStream(randomAccessFile);
            // 自动模式
            if (usePassword) {
                inArchive = SevenZip.openInArchive(null , inStream, password);
            } else {
                inArchive = SevenZip.openInArchive(null, inStream);
            }
            ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
            ISimpleInArchiveItem[] archiveItems = simpleInArchive.getArchiveItems();
            for (ISimpleInArchiveItem item : archiveItems) {
                RandomAccessFileOutStream rafo = null;
                try {
                    File file;
                    if (item.isFolder()) {
                        new File(outFile , item.getPath()).mkdirs();
                        continue;
                    } else {
                        file = new File(outFile , item.getPath());
                        if (! file.getParentFile().exists()) {
                            file.getParentFile().mkdirs();
                        }
                    }

                    rafo = new RandomAccessFileOutStream(new RandomAccessFile(file , "rw"));
                    if (usePassword) {
                        item.extractSlow(rafo , password);
                    } else {
                        item.extractSlow(rafo);
                    }
                    resultList.add(file);
                } finally {
                    if (rafo != null) {
                        rafo.close();
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            IOUtils.closeQuietly(inStream);
            IOUtils.closeQuietly(inArchive);
        }
        return resultList;
    }

}

3.测试代码

package cn.chendd.compress;

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.MethodSorters;

import java.io.File;

/**
 * 测试rar格式压缩包文件的操作
 *
 * @author chendd
 * @date 2023/3/5 19:29
 */
@RunWith(JUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CompressRarTest {

    /**
     * 测试文件生成rar
     */
    @Test
    public void toRarFile() {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File file = new File(projectHome , "源文件/哈喽.txt");
        File zipFile = new File(projectHome , "压缩文件夹/7zipjbinging_哈喽.rar");
        CompressRar.sevenZ(file , zipFile);
        System.out.println("压缩源文件:" + file.getAbsolutePath());
        System.out.println("压缩后文件:" + zipFile.getAbsolutePath());
    }

    /**
     * 测试文件夹生成rar
     */
    @Test
    public void toRarFolder() {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File file = new File(projectHome , "源文件/复杂文件夹");
        File zipFile = new File(projectHome , "压缩文件夹/7zipjbinging_复杂文件夹.rar");
        CompressRar.sevenZ(file , zipFile);
        System.out.println("压缩源文件:" + file.getAbsolutePath());
        System.out.println("压缩后文件:" + zipFile.getAbsolutePath());
    }

    /**
     * 测试带密码的文件夹生成rar(加密文件名)
     */
    @Test
    public void toRarPasswordFolder() {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File file = new File(projectHome , "源文件/简单文件夹");
        File zipFile = new File(projectHome , "压缩文件夹/7zipjbinging_带密码_简单文件夹.rar");
        CompressRar.sevenZ(file , zipFile , "https://www.chendd.cn");
        System.out.println("压缩源文件:" + file.getAbsolutePath());
        System.out.println("压缩后文件:" + zipFile.getAbsolutePath());
    }

    /**
     * 解压缩 rar 文件
     */
    @Test
    public void unRarFile() {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File zipFile = new File(projectHome , "压缩文件夹/7zipjbinging_复杂文件夹.rar");
        File file = new File(projectHome , "解压缩文件夹/7zipjbinging_复杂文件夹");
        CompressRar.unSevenZ(zipFile , file);
        System.out.println("压缩源文件:" + file.getAbsolutePath());
        System.out.println("解压缩后文件:" + zipFile.getAbsolutePath());
    }

    /**
     * 解压缩带密码的 rar 文件
     */
    @Test
    public void unRarPasswordFile() {
        File projectHome = new File(System.getProperty("user.dir")).getParentFile();
        File zipFile = new File(projectHome , "压缩文件夹/7zipjbinging_带密码_简单文件夹.rar");
        File file = new File(projectHome , "解压缩文件夹/7zipjbinging_带密码_简单文件夹");
        CompressRar.unSevenZ(zipFile , file , "https://www.chendd.cn");
        System.out.println("压缩源文件:" + file.getAbsolutePath());
        System.out.println("解压缩后文件:" + zipFile.getAbsolutePath());
    }

}

4.运行示例

image.png

(压缩文件示例)

image.png

(提取带密码的Rar文件预览)

5.实现说明

(1)本文使用开源项目7-Zip-Jbinding 实现的“rar”格式文件(夹)的压缩和解压缩,仅以rar格式文件的操作进行示例实践;

(2)本文示例包含文件压缩、文件解压缩、文件夹压缩、文件夹解压缩、压缩包文件列表预览;

(4)本文示例支持压缩文件(夹)包含中文名称,支持带密码文件的压缩和解压缩;

(5)项目源码下载地址:“https://gitee.com/88911006/chendd-examples/tree/master/compress”,详见7zipjbinding模块;

 点赞


 发表评论

当前回复:作者

 评论列表


留言区