JAVA解压tar、zip、rar、gz、7z文件

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>

 <!-- zip解压依赖 -->    
 <dependency>     
    <groupId>org.apache.ant</groupId>     
    <artifactId>ant</artifactId>     
    <version>1.10.10</version>     
</dependency>

<!-- 7z解压依赖 --> 
<dependency>
    <groupId>org.tukaani</groupId>
    <artifactId>xz</artifactId>
    <version>1.9</version>
</dependency>

 

2、具体逻辑代码

/**
 * @description:  解压tar到指定的文件夹
 * @date: 2023/11/13 14:34
 * @param sourceFile  源文件绝对路径
 * @param destDir  要解压到的目录地址
 * @return boolean
 */
public static boolean unTar(String sourceFile, String destDir) {
    boolean flag = false;
    try (FileInputStream fis = new FileInputStream(sourceFile);
         BufferedInputStream bis = new BufferedInputStream(fis);
         TarArchiveInputStream tarInputStream = new TarArchiveInputStream(bis)) {
        TarArchiveEntry tarEntry;
        while ((tarEntry = tarInputStream.getNextTarEntry()) != null) {
            File outputFile = new File(destDir, tarEntry.getName());
            if (tarEntry.isDirectory()) {
                outputFile.mkdirs();
            } else {
                outputFile.getParentFile().mkdirs();
                try (OutputStream outputStream = new FileOutputStream(outputFile)) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = tarInputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }
            }
        }
        flag = true;
    } catch (IOException e) {
        log.info("解压tar文件失败:{}, {}", sourceFile, e.toString());
    }
    return flag;
}


/**
 * @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 srcPath, String destDirPath) {
    boolean flag = false;
    File srcFile = new File(srcPath);
    if (!srcFile.exists()) {
        throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
    }
    // 开始解压
    ZipFile zipFile = null;
    try {
        zipFile = new ZipFile(srcFile);
        // zipFile = new ZipFile(srcFile, Charset.forName("GBK")); //含有中文 使用java.util.zip才需要指定这个,后面即使指定了也还是有问题,所以放弃这个改成Ant.jar
        Enumeration <? > entries = zipFile.getEntries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            System.out.println("解压" + entry.getName());
            // 如果是文件夹,就创建个文件夹
            if (entry.isDirectory()) {
                String dirPath = destDirPath + "/" + entry.getName();
                File dir = new File(dirPath);
                dir.mkdirs();
            } else {
                // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                File targetFile = new File(destDirPath + "/" + entry.getName());
                // 保证这个文件的父文件夹必须要存在
                if (!targetFile.getParentFile().exists()) {
                    targetFile.getParentFile().mkdirs();
                }
                targetFile.createNewFile();
                // 将压缩文件内容写入到这个文件中
                InputStream is = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(targetFile);
                int len;
                byte[] buf = new byte[2048];
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                }
                // 关流顺序,先打开的后关闭
                fos.close();
                is.close();
            }
        }
        flag = true;
    } catch (Exception e) {
        log.error("解析压缩包文件异常:{}", srcPath);
        throw new RuntimeException("unzip error from ZipUtils", e);
    } finally {
        if (zipFile != null) {
            try {
                zipFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return flag;
}

/**
 * @description:  解压7z到指定的文件夹
 * @date: 2023/5/29 18:13
 * @param filePath  源文件绝对路径
 * @param destDir  要解压到的目录地址
 * @return boolean
 */
 public static boolean un7z(String filePath, String descDir){
    boolean flag = false;
    SevenZFile zIn = null;
    try {
        File file = new File(filePath);
        zIn = new SevenZFile(file);
        SevenZArchiveEntry entry = null;
        while ((entry = zIn.getNextEntry()) != null){
            if(!entry.isDirectory()){
                File newFile = new File(descDir, entry.getName());
                if(!newFile.exists()){
                    new File(newFile.getParent()).mkdirs();
                }
                OutputStream out = new FileOutputStream(newFile);
                BufferedOutputStream bos = new BufferedOutputStream(out);
                int len = -1;
                byte[] buf = new byte[(int)entry.getSize()];
                while ((len = zIn.read(buf)) != -1){
                    bos.write(buf, 0, len);
                }
                bos.flush();
                bos.close();
                out.close();
            }
        }
        flag = true;
    } catch (Exception e) {
        log.info("解压7z出错 {}, {}", filePath,e.getMessage());
    }finally {
        try {
            if (zIn != null) zIn.close();
        } catch (IOException e) {
            log.info("解压7z后关闭文件流程失败 {}, {}", filePath,e.getMessage());
        }
    }
    return flag;
}

/**
 * @description:  解压gzip到指定的文件夹  注意解压出来的直接是一个文件
 * @date: 2023/8/23 15:16
 * @param sourceFile  源文件绝对路径
 * @param targetFolder  要解压到的目录地址
 * @return boolean
 */
public static boolean unGzip(String sourceFile,String targetFolder){
    boolean flag = false;
    try {
        FileInputStream fin = new FileInputStream(sourceFile);
        //建立gzip解压工作流
        GZIPInputStream gzin = new GZIPInputStream(fin);
        //建立解压文件输出流
        File file = new File(sourceFile);
        String fileName = file.getName();
        targetFolder = targetFolder + "/" + fileName.substring(0, fileName.lastIndexOf('.'));
        FileOutputStream fout = new FileOutputStream(targetFolder);

        int num;
        byte[] buf=new byte[1024];

        while ((num = gzin.read(buf,0,buf.length)) != -1)
        {
            fout.write(buf,0,num);
        }

        gzin.close();
        fout.close();
        fin.close();

        flag = true;
    } catch (IOException e) {
        log.info("解压gz文件失败:{}, {}",sourceFile,e.getMessage());
    }
    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());
            }
        }
    }
}

 

posted @ 2023-07-02 16:38  bug毁灭者  阅读(1306)  评论(0编辑  收藏  举报