zip和rar解压

发布时间 2023-08-23 16:58:55作者: 爱编程_喵

zip和rar解压

maven依赖

<dependencies>
        <!-- zip和rar压缩包处理-->
        <dependency>
            <groupId>com.github.axet</groupId>
            <artifactId>java-unrar</artifactId>
            <version>1.7.0-8</version>
        </dependency>
        <dependency>
            <groupId>net.sf.sevenzipjbinding</groupId>
            <artifactId>sevenzipjbinding</artifactId>
            <version>16.02-2.01</version>
        </dependency>
        <dependency>
            <groupId>net.sf.sevenzipjbinding</groupId>
            <artifactId>sevenzipjbinding-all-platforms</artifactId>
            <version>16.02-2.01</version>
        </dependency>

        <!-- 常用工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>
</dependencies>

相关实例

package utils;

import net.sf.sevenzipjbinding.*;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


/**
 * rar解压回调处理类
 */
class ExtractCallback implements IArchiveExtractCallback {
    private int index;
    private IInArchive inArchive;
    private String ourDir;
    private HashSet<String> fl;


    public ExtractCallback(IInArchive inArchive, String ourDir, HashSet<String> fl) {
        this.inArchive = inArchive;
        this.ourDir = ourDir;
        this.fl = fl;
    }

    @Override
    public void setCompleted(long arg0) throws SevenZipException {
    }

    @Override
    public void setTotal(long arg0) throws SevenZipException {
    }

    @Override
    public ISequentialOutStream getStream(int index, ExtractAskMode extractAskMode) throws SevenZipException {
        this.index = index;
        return data -> {
            String rarInfo = inArchive.getStringProperty(index, PropID.PATH);
            boolean isFolder = (boolean) inArchive.getProperty(index, PropID.IS_FOLDER);
            rarInfo = rarInfo.replace("\\", "/");
            FileOutputStream fos = null;
            try {
                String targetPath;
                // 过滤-解压特定格式文件(png|jpg|jpeg|pdf)
                String[] suffixArr = {".png", ".jpg", ".jpeg", ".pdf", ".zip", ".rar"};
                if (StringUtils.isBlank(rarInfo) || rarInfo.lastIndexOf(".") == -1){
                    rarInfo = "";
                    isFolder = true;
                }else{
                    String suffix = rarInfo.substring(rarInfo.lastIndexOf("."));
                    suffix = suffix.toLowerCase();
                    if (!ArrayUtils.contains(suffixArr, suffix)){
                        rarInfo = "";
                        isFolder = true;
                    }
                }

                if (StringUtils.isNotBlank(rarInfo) && rarInfo.lastIndexOf(".") != -1){
                    // 判断压缩包内是否多层目录
                    if (rarInfo.lastIndexOf("/") != -1){
                        String suffix = rarInfo.substring(rarInfo.lastIndexOf("/")+1);
                        // 获取上一级目录
                        String[] rarInfoSplit = rarInfo.split("/");
                        String beforeDir = rarInfoSplit[rarInfoSplit.length-2];
                        targetPath = ourDir + "/"  + suffix;
                    } else{
                        targetPath = ourDir + "/" + rarInfo;
                    }
                } else {
                    targetPath = ourDir + "/" + rarInfo;
                    isFolder = true;
                }
                File file = new File(targetPath);
                if (!file.getParentFile().exists()){
                    file.getParentFile().mkdirs();
                }
                if (!file.exists()){
                    file.createNewFile();
                }
                // 写入数据
                fos = new FileOutputStream(file, true);
                fos.write(data);
                if (file.exists() && file.isFile()){
                    fl.add(file.getAbsolutePath());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try{
                    if (fos != null){
                        fos.flush();
                        fos.close();
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            return data.length;
        };
    }


    @Override
    public void prepareOperation(ExtractAskMode arg0) throws SevenZipException {
    }

    @Override
    public void setOperationResult(ExtractOperationResult extractOperationResult) throws SevenZipException {}

}


/**
 * 压缩包工具类
 */
public class PackageUtils {

    private static final int buffer = 2048;

    /**
     * 整合解压压缩包
     * @param packagePath
     * @param savePath
     * @return
     */
    public static HashSet<String> unPackage(String packagePath, String savePath){
        HashSet<String> fsl = new HashSet<>();
        String suffix = packagePath.substring(packagePath.lastIndexOf("."));
        if (StringUtils.isBlank(suffix)){
            return fsl;
        }
        if (suffix.equals(".rar")){
            fsl = unRar(packagePath, savePath);
        } else if (suffix.equals(".zip")) {
            fsl = unZip(packagePath, savePath);
        }
        System.out.println("unPackage(" + fsl.size() + "|"+ packagePath + "):" +  fsl);
//        // 解压完成 压缩包删除
//        boolean deleteFlag = deleteFile(packagePath);
//        log.info("deletePackage({}):{}", packagePath, deleteFlag);
        return fsl;
    }


    /**
     * 解压Zip文件
     * @param zipFilePath
     * @param destDir
     */
    public static HashSet<String> unZip(String zipFilePath, String destDir) {
        HashSet<String> pathList = new HashSet<>();
        File destFile = new File(destDir);
        File zipFile = new File(zipFilePath);
        destDir = destDir.replace("\\", "/");
        zipFilePath = zipFilePath.replace("\\", "/");
        String zipName = "";

        if (!destFile.exists()){
            destFile.mkdirs();
        }
        if (!zipFile.exists()){
            System.out.println("unZipError:" + zipFilePath + "is not exists");
            return pathList;
        }
        if (!destDir.endsWith("/")){
            destDir += "/";
        }

        System.setProperty("sun.zip.encoding", System.getProperty("sun.jnu.encoding")); //防止文件名中有中文时出错
        FileInputStream fis;
        byte[] myBuffer = new byte[buffer];
        try {
            fis = new FileInputStream(zipFilePath);
            ZipInputStream zis = new ZipInputStream(fis, Charset.forName("gbk"));
            ZipEntry ze = null;
            while ((ze = zis.getNextEntry())!= null) {
                String fileName = ze.getName();
//                // 过滤文件夹和非匹配的文件
                if (StringUtils.isBlank(fileName) || fileName.lastIndexOf(".") == -1 || ze.isDirectory()){
                    continue;
                }

                String[] suffixArr = {".png", ".jpg", ".jpeg", ".pdf", ".zip", ".rar"};
                String suffix = fileName.substring(fileName.lastIndexOf("."));
                suffix = suffix.toLowerCase();
                if (!ArrayUtils.contains(suffixArr, suffix)){
                    continue;
                }
                // 压缩包相关文件随机名
                fileName = fileName.replace("\\", "/");
                String outPath;

                if (zipFilePath.lastIndexOf("/") != -1){
                    String substring = zipFilePath.substring(zipFilePath.lastIndexOf("/") + 1);
                    if (zipFilePath.lastIndexOf("-")!=-1){
                        zipName = substring.substring(substring.lastIndexOf("-")+1, substring.lastIndexOf("."));
                    }else{
                        zipName = substring.substring(0, substring.lastIndexOf("."));
                    }
                }

                if (fileName.lastIndexOf("/") != -1){
                    // 默认上一级压缩包名
                    String _suffix = fileName.substring(fileName.lastIndexOf("/") + 1);
                    outPath = destDir + UUID.randomUUID().toString().replace("-", "")  +"[" + zipName + "]"+ "-" + _suffix;
                }else{
                    outPath = destDir +  UUID.randomUUID().toString().replace("-", "")  +"[" + zipName + "]"+  "-" + fileName;
                }
                // 判断路径是否存在,不存在则创建
                File newFile = new File(outPath.substring(0, outPath.lastIndexOf("/")));
                if (!newFile.exists()){
                    newFile.mkdirs();
                }
                if (new File(outPath).isDirectory()){
                    continue;
                }
                FileOutputStream fos = new FileOutputStream(outPath);
                int len;
                while ((len = zis.read(myBuffer)) > 0) {
                    fos.write(myBuffer, 0, len);
                }
                fos.close();
                zis.closeEntry();
                pathList.add(outPath);
                // 递归解压
                if (fileName.endsWith(".zip") || fileName.endsWith(".ZIP") || fileName.endsWith(".RAR") || fileName.endsWith(".rar")){
                    HashSet<String> strings = unPackage(outPath, destDir);
                    // 删除临时压缩包
                    boolean deleteFlag = deleteFile(outPath);
                    System.out.println("deletePackage("+ outPath + "):" + deleteFlag);
                    pathList.addAll(strings);
                }
                pathList.removeIf(fp->fp.endsWith(".rar") || fp.endsWith("RAR") || fp.endsWith(".zip") || fp.endsWith(".ZIP"));
            }
            zis.closeEntry();
            zis.close();
            fis.close();
        }
        catch (IOException e) {
            System.out.println("unZipError(" + zipFilePath + "):" + String.valueOf(e));
        }
        return pathList;
    }


    /**
     * 解压Rar文件
     * @param rarPath rar文件路径
     * @param savePath 存储路径
     */
    public static HashSet<String> unRar(String rarPath, String savePath) {
        HashSet<String> fileSet = new HashSet<>();
        File rarFile = new File(rarPath);
        if (!rarFile.exists()){
            System.out.println("unRarError:" + rarPath + "is not exists");
            return fileSet;
        }
        IInArchive archive = null;
        RandomAccessFile randomAccessFile = null;
        try{
            randomAccessFile = new RandomAccessFile(rarPath, "r");
//            archive = SevenZip.openInArchive(ArchiveFormat.RAR5, new RandomAccessFileInStream(randomAccessFile));
            // null:自动识别
            archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
            int[] in = new int[archive.getNumberOfItems()];
            for (int i = 0; i < in.length; i++) {
                in[i] = i;
            }
            archive.extract(in, false, new ExtractCallback(archive, savePath, fileSet));
            archive.close();
            randomAccessFile.close();
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("unRarError("+ rarPath + "):" + e);
        }
        // 递归解压
        for (String fp: fileSet) {
            if (fp.endsWith(".zip") || fp.endsWith(".ZIP") || fp.endsWith(".RAR") || fp.endsWith(".rar")){
                HashSet<String> strings = unPackage(fp, savePath);
                // 删除临时压缩包
                boolean deleteFlag = deleteFile(fp);
                System.out.println("deletePackage(" + fp + "):" + deleteFlag);
                fileSet.addAll(strings);
            }
        }
        // 剔除不需要的数据
        fileSet.removeIf(fp -> fp.endsWith(".zip") || fp.endsWith(".ZIP") || fp.endsWith(".RAR") || fp.endsWith(".rar"));
        return fileSet;
    }

    /**
     * 删除临时文件
     * @param filePath
     * @return
     */
    public static boolean deleteFile(String filePath){
        boolean flag = false;
        File file = new File(filePath);
        if (file.isFile() && file.exists()){
            file.delete();
            flag = true;
        }
        return flag;
    }


    public static void main(String[] args) {
        unPackage("F:/test/tmp/test.zip", "F:/test/download/zip");
//        System.out.println("=======================================================================");
        unPackage("F:/test/tmp/test.rar", "F:/test/download/rar");
    }
}