ZipInputStream - 解压缩文件的功能方法

Posted

技术标签:

【中文标题】ZipInputStream - 解压缩文件的功能方法【英文标题】:ZipInputStream - functional approach to unzip files 【发布时间】:2022-01-02 04:14:58 【问题描述】:

我有一个仅包含文件而不包含目录的 zip 文件。我想仅使用功能 Java 将文件解压缩到一个目录中。

下面的代码按预期工作并将文件解压缩到目标文件夹中。

public static void unzip(Path source, Path target) throws IOException 

    try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) 

        ZipEntry zipEntry = zis.getNextEntry();

        while (zipEntry != null) 

            Path targetDirResolved = target.resolve(zipEntry.getName());

            Path normalizePath = targetDirResolved.normalize();
            if (!normalizePath.startsWith(target)) 
                throw new IOException("Bad zip entry: " + zipEntry.getName());
            

            Files.copy(zis, normalizePath, StandardCopyOption.REPLACE_EXISTING);

            zipEntry = zis.getNextEntry();

        
        zis.closeEntry();

    

我想实现与上述相同的功能,但使用更实用的方法。

我最初的想法是将 while 循环转换为 IntStream.range(0, ).... 之类的东西,但 zip 文件中的条目数未知。

有什么想法吗?

【问题讨论】:

【参考方案1】:

消除while循环的一种方法是使用ZipFilestream:

try (ZipFile fs = new ZipFile(source.toFile())) 
    fs.stream()
      .filter(Predicate.not(ZipEntry::isDirectory))
      // etc
      .forEach(System.out::println);

您还可以查看带有Files.find 的 ZIP 文件系统,以提供合适的 ZIP 条目Stream(一级文件),如果需要,对流进行额外的过滤/映射或其他转换,而不是 forEach如图所示:

try (FileSystem fs = FileSystems.newFileSystem(source)) 
    for (Path root : fs.getRootDirectories()) 
        try (Stream<Path> stream = Files.find(root, 1, (p,a) -> a.isRegularFile())) 
            stream.forEach(p -> copy(p, Path.of(target.toString(), p.toString())));
        
    

不幸的是,上面仍然对根目录使用正常循环,copy 是处理IOException 的单独方法:

private static void copy(Path from, Path to) 
    try 
        Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
    
    catch (IOException e) 
        throw new UncheckedIOException(e);
    

【讨论】:

以上是关于ZipInputStream - 解压缩文件的功能方法的主要内容,如果未能解决你的问题,请参考以下文章

java程序压缩和解压zip文件

Android:打开大型 zip 文件

ZipInputStream和RSA算法的纠葛

如何在不写入输出流的情况下从 ZipInputStream 获取每个 ZipFile 条目的字节/内容?

java 如何读取本地硬盘上面的zip文件. 返回ZipInputStream流!

Linux下的tar归档及解压缩功能详解