JAVA解压tar、zip、rar文件

发布时间 2023-07-02 16:42:49作者: bug毁灭者

1、添加pom依赖

      <!-- tar解压依赖 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.20</version>
        </dependency>

        <!-- rar解压依赖 -->
        <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>

2、具体逻辑代码

/**
     * @description:  解压tar.gz到指定的文件夹
     * @date: 2023/5/29 17:56
     * @param sourceFile  源文件绝对路径
     * @param destDir  要解压到的目录地址
     * @return boolean
     */
    public static boolean unTarGz(String sourceFile, String destDir) {
        Path source = Paths.get(sourceFile);
        Path target = Paths.get(destDir);
        boolean flag = false;
        try (InputStream fi = Files.newInputStream(source);
             BufferedInputStream bi = new BufferedInputStream(fi);
             GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
             TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {
            ArchiveEntry entry;
            while ((entry = ti.getNextEntry()) != null) {
                String entryName = entry.getName();
                Path targetDirResolved = target.resolve(entryName);
                Path newDestPath = targetDirResolved.normalize();
                if (entry.isDirectory()) {
                    newDestPath = Paths.get(destDir + "/" + entryName);
                    Files.createDirectories(newDestPath);
                } else {
                    Files.copy(ti, newDestPath, StandardCopyOption.REPLACE_EXISTING);
                }
            }
            flag = true;
        } catch (Exception e) {
            log.info("解压tar.gz文件失败:{},{}", sourceFile, e);
        }
        return flag;
    }

/**
     * @description:  解压zip到指定的文件夹
     * @date: 2023/5/29 17:56
     * @param sourceFile  源文件绝对路径
     * @param destDir  要解压到的目录地址
     * @return boolean
     */
public static boolean unZip(String zipPath, String descDir) {
        boolean flag = false;
        try (FileInputStream fis = new FileInputStream(zipPath);
             ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis), Charset.forName("GBK"))) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                log.info("Unzipping: " + entry.getName());
                if (entry.getName().endsWith("/")) {
                    File pathFile = new File(descDir + "/" + entry.getName());
                    if (!pathFile.exists()) {
                        pathFile.mkdirs();
                    }
                    continue;
                }
                int size;
                byte[] buffer = new byte[2048];
                String destFile = descDir + "\\" + entry.getName();
                destFile = destFile.replaceAll("\\\\", "/");
                File fileOut = new File(destFile);
                try (FileOutputStream fos = new FileOutputStream(fileOut);
                     BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.length)) {
                    while ((size = zis.read(buffer, 0, buffer.length)) != -1) {
                        bos.write(buffer, 0, size);
                    }
                    bos.flush();
                }
            }
            flag = true;
        } catch (IOException e) {
            log.info("解压zip文件失败:{},{}", zipPath, e);
        }
        return flag;
    }


/**
     * @description:  解压rar到指定的文件夹
     * @date: 2023/5/29 17:56
     * @param sourceFile  源文件绝对路径
     * @param destDir  要解压到的目录地址
     * @return boolean
     */
public static boolean unRar(String rarPath, String descDir){
        if (!descDir.endsWith("/")) {
            descDir = descDir + "/";
        }
        File pathFile = new File(descDir);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        File rarFile = new File(rarPath);
        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(rarFile.toString(), "r");
            IInArchive 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, pathFile.getAbsolutePath() + "/"));
            archive.close();
            randomAccessFile.close();
            return true;
        } catch (Exception e) {
            log.error("解压rar出错 {}", e.getMessage());
            return false;
        }
    }

/**
     * @description:  解压rar辅助类
     */
public class ExtractCallback implements IArchiveExtractCallback{

        private Logger log = LoggerFactory.getLogger(ExtractCallback.class);

        private int index;
        private IInArchive inArchive;
        private String ourDir;

        public ExtractCallback(IInArchive inArchive, String ourDir) {
            this.inArchive = inArchive;
            this.ourDir = ourDir;
        }

        @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;
            String path = (String) inArchive.getProperty(index, PropID.PATH);
            final boolean isFolder = (boolean) inArchive.getProperty(index, PropID.IS_FOLDER);
            String finalPath = path;
            File newfile = null;
            try {
                String fileEnd = "";
                //对文件名,文件夹特殊处理
                if (finalPath.contains(File.separator)) {
                    fileEnd = finalPath.substring(finalPath.lastIndexOf(File.separator) + 1);
                } else {
                    fileEnd = finalPath;
                }
                finalPath = finalPath.substring(0, finalPath.lastIndexOf(File.separator) + 1) + fileEnd;
                //目录层级
                finalPath = finalPath.replaceAll("\\\\", "/");
                String suffixName = "";
                int suffixIndex = fileEnd.lastIndexOf(".");
                if (suffixIndex != -1) {
                    suffixName = fileEnd.substring(suffixIndex + 1);
                }
                newfile = createFile(isFolder, ourDir + finalPath);
                final boolean directory = (boolean) inArchive.getProperty(index, PropID.IS_FOLDER);
            } catch (Exception e) {
                log.error("rar解压失败{}", e.getMessage());
            }
            File finalFile = newfile;
            return data -> {
                save2File(finalFile, data);
                return data.length;
            };
        }

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

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

        public  File createFile(boolean isFolder, String path) {
            //前置是因为空文件时不会创建文件和文件夹
            File file = new File(path);
            try {
                if (!isFolder) {
                    File parent = file.getParentFile();
                    if ((!parent.exists())) {
                        parent.mkdirs();
                    }
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                } else {
                    if ((!file.exists())) {
                        file.mkdirs();
                    }
                }
            } catch (Exception e) {
                log.error("rar创建文件或文件夹失败 {}", e.getMessage());
            }
            return file;
        }

        public  boolean save2File(File file, byte[] msg) {
            OutputStream fos = null;
            try {
                fos = new FileOutputStream(file, true);
                fos.write(msg);
                fos.flush();
                return true;
            } catch (FileNotFoundException e) {
                log.error("rar保存文件失败{}", e.getMessage());
                return false;
            } catch (IOException e) {
                log.error("rar保存文件失败{}", e.getMessage());
                return false;
            } finally {
                try {
                    fos.close();
                } catch (IOException e) {
                    log.error("rar保存文件失败{}", e.getMessage());
                }
            }
        }
}