java库学习之commons-compress实现zip包的压缩和解压

commons-compress

依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.21</version>
</dependency>

官方文档

Commons Compress – Commons Compress User Guide

使用

解压zip包

注:多层,中文可以使用ZipArchiveInputStream但读入在mkdir和生成文件时会出错(乱码)

ZipInputStream无法读入中文文件名的文件盒文件夹,抛出异常报错

/**
     * 解压zip包至目标目录下,若目录不存在会自动新建;
     * utf-8编码的zip文件中存在gbk编码的文件和文件夹,解码会有乱码
     * 文件夹名称存在中文的,新建文件夹会失败,采取跳过的策略
     * 若存在中文命名的文件会抛出异常,采取跳过的策略
     * @param inputStream 输入的文件流
     * @Param destDir 解压的目标地址
     */
    public void unzip(InputStream inputStream, String destDir) {
        ArchiveEntry zipEntry;
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
             ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(bufferedInputStream)) {
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                File file = new File(destDir, zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    boolean mkdirs = file.mkdirs();
                    if (!mkdirs) {
                        log.info("make dir fails, dir exists Chinese");
                    }
                } else {
                    try (FileOutputStream outPut = FileUtils.openOutputStream(file);
                         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outPut)) {
                        IOUtils.copy(zipInputStream, bufferedOutputStream, 8192);
                    } catch (IOException e) {
                        log.info("file exists Chinese");
                    }
                }
            }
        } catch (IOException e) {
            log.info("have an IOException", e);
            throw new RuntimeException("解压失败", e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.info("failed to close the input stream");
            }
        }
    }

压缩多层文件到zip包中(使用ZipOutputStream,非commons-compress库的使用)

/**
     * 压缩文件(文件夹)为zip包
     * @param sourceFile
     * @param targetZipFile
     * @param base
     * @throws IOException
     */
    public void zipFiles(File sourceFile, File targetZipFile, String base) throws IOException {
        ZipOutputStream outputStream = null;
        try {
            outputStream = new ZipOutputStream(new FileOutputStream(targetZipFile));
            for (File file : sourceFile.listFiles()) {
                addEntry("", file, outputStream, base);
            }
        } catch (Exception e) {
            throw new IOException(e);
        } finally {
            outputStream.close();
        }
    }

    private void addEntry(String dir, File inFile, ZipOutputStream out, String base) throws IOException {
        if (inFile.isDirectory()) {
            File[] files = inFile.listFiles();
            if (files != null && files.length > 0) {
                for (File file : files) {
                    String name = inFile.getName();
                    if (!"".equals(dir)) {
                        name = dir + "/" + name;
                    }
                    addEntry(name, file, out, base);
                }
            }
        } else {
            doZip(inFile, out, dir, base);
        }


    }

    private void doZip(File inFile, ZipOutputStream out, String dir, String base) throws IOException {
        String entryName = null;
        if (!"".equals(dir)) {
            entryName = dir + "/" + inFile.getName();
        } else {
            entryName = inFile.getName();
        }
        log.info("zip entryName is "+entryName);
        ZipEntry entry = new ZipEntry(entryName);
        out.putNextEntry(entry);

        int len = 0 ;
        byte[] buffer = new byte[1024];
        FileInputStream fis = new FileInputStream(inFile);
        while ((len = fis.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            out.flush();
        }
        out.closeEntry();
        fis.close();
    }

压缩单个或多层文件到zip包中(使用ZipArchiveOutputStream)

 /**
     * 支持单文件或多层文件夹的压缩
     *
     * @param srcPath
     * @param targetPath
     */
    public static void zipFile(String srcPath, String targetPath) {
        int length;
        File file = new File(srcPath);
        List<File> filesToArchive;
        if (file.isDirectory()) {
            filesToArchive = getAllFile(new File(srcPath));
            length= srcPath.length();
        } else {
            filesToArchive = Collections.singletonList(file);
            length = file.getParent().length()+1;
        }
        try (ArchiveOutputStream o = new ZipArchiveOutputStream(new File(targetPath))) {
            for (File f : filesToArchive) {
                ArchiveEntry entry = o.createArchiveEntry(f, f.getPath().substring(length));
                o.putArchiveEntry(entry);
                if (f.isFile()) {
                    try (InputStream i = Files.newInputStream(f.toPath())) {
                        IOUtils.copy(i, o);
                    }
                }
                o.closeArchiveEntry();
            }
        } catch (IOException e) {
            logger.error("zipFile fails", e);
        }
    }

    public static List<File> getAllFile(File dirFile) {
        File[] childrenFiles = dirFile.listFiles();
        if (Objects.isNull(childrenFiles) || childrenFiles.length == 0) {
            return Collections.emptyList();
        }
        List<File> files = new ArrayList<>();
        for (File childFile : childrenFiles) {
            if (childFile.isFile()) {
                files.add(childFile);
            } else {
                files.add(childFile);
                List<File> cFiles = getAllFile(childFile);
                if (cFiles.isEmpty()) {
                    continue;
                }
                files.addAll(cFiles);
            }
        }
        return files;
    }

使用

    @Test
    public void testZipFile_use_file() {
        String srcPath = "D:/log/aa/QueryResult1656385398596.csv";
        String targetPath = "D:/log/aa/tmp.zip";
        ZipUtil.zipFile(srcPath,targetPath);
    }

    @Test
    public void testZipFile_use_dir() {
        String srcPath = "D:/log/aa/";
        String targetPath = "D:/log/aa/tmp.zip";
        ZipUtil.zipFile(srcPath,targetPath);
    }

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Apache Commons Compress 是一个用于处理压缩文件的开源 Java ,它支持多种压缩格式,ZIP、TAR、GZIP、BZIP2 等。 下面是使用 Apache Commons Compress 实现文件压缩解压的示例代码: ## 压缩文件 ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; public class FileCompressor { public static void compress(File source, File destination) throws Exception { try (FileOutputStream fos = new FileOutputStream(destination); GzipCompressorOutputStream gzos = new GzipCompressorOutputStream(fos); TarArchiveOutputStream tos = new TarArchiveOutputStream(gzos)) { ArchiveEntry entry = new TarArchiveEntry(source.getName()); entry.setSize(source.length()); tos.putArchiveEntry(entry); FileInputStream fis = new FileInputStream(source); byte[] buffer = new byte[4096]; int count; while ((count = fis.read(buffer)) != -1) { tos.write(buffer, 0, count); } fis.close(); tos.closeArchiveEntry(); } } } ``` ## 解压文件 ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; public class FileExtractor { public static void extract(File source, File destination) throws Exception { try (FileInputStream fis = new FileInputStream(source); GzipCompressorInputStream gzis = new GzipCompressorInputStream(fis); ArchiveInputStream ais = new TarArchiveInputStream(gzis)) { ArchiveEntry entry; while ((entry = ais.getNextEntry()) != null) { if (!ais.canReadEntryData(entry)) { continue; } File file = new File(destination, entry.getName()); if (entry.isDirectory()) { file.mkdirs(); } else { FileOutputStream fos = new FileOutputStream(file); byte[] buffer = new byte[4096]; int count; while ((count = ais.read(buffer)) != -1) { fos.write(buffer, 0, count); } fos.close(); } } } } } ``` 以上是使用 Apache Commons Compress 实现文件压缩解压的示例代码,你可以根据自己的需求进行修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值