【问题标题】:Java ZipInputStream throws zip.ZipException: invalid distance too far back while parsing nested zip filesJava ZipInputStream 抛出 zip.ZipException:在解析嵌套的 zip 文件时无效距离太远
【发布时间】:2019-10-29 09:36:12
【问题描述】:

我首先要承认我已经在这里和互联网上阅读了几个主题,但我的问题仍然存在并且似乎有所不同。

我有一个 zip 文件,其中包含几个 .txt 文件、目录、该目录的子目录等。里面还有很多 zip 档案,里面有 zip、目录和文件。最深层次的归档是 5 个步骤 -> 5 个 zip,一个在另一个内部,带有不同的文件。

我有这个代码:

ZipFile zipFile = new ZipFile(Objects.requireNonNull(this.classLoader.getResource("inputs.zip")).getFile());
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        InputStream stream = zipFile.getInputStream(entry);
        System.out.println(entry.getName());
        processZipFile(stream);
    }

这里是 processZipFile:

private void processZipFile(InputStream stream) throws IOException {
    ZipInputStream zipInputStream = new ZipInputStream(stream);
    ZipEntry zipEntry = zipInputStream.getNextEntry();
    while (zipEntry != null) {
        System.out.print("    /" + zipEntry.getName());
        if (zipEntry.getName().endsWith(".zip")) {
            processZipFile(stream);
        }
        zipEntry = zipInputStream.getNextEntry();
    }

在归档 3 级之前,一切似乎都运行良好,列出了所有目录、zip、gzip 和子目录,但是当涉及到处理诸如 inputs.zip/1.zip/2.zip 之类的内容时,它会抛出异常

Exception in thread "main" java.util.zip.ZipException: invalid distance too far back

正如我在 Java 8 文档 ZipInputStream.getNextEntry() 中所读到的: Reads the next ZIP file entry and positions the stream at the beginning of the entry data. 因为刚拿到入口程序就抛出异常。

在这种情况下,“2.zip”中的文件相当大 - 800 MB 与其他最大大小为 3 MB 的情况相比 - 我想知道它是否会影响程序。

我正在尝试在不打开这些拉链的情况下完成所有这些事情,这在这里非常重要。我知道这种错误通常与损坏的 zip 文件有关,但这些错误是完全合法的。

所以我的问题是 - 我如何才能浏览所有这些嵌套的 zip 文件?

编辑/解决方案:

根据 Talex 提出的更改,我已将代码修复为在 ZipInputStreams 而非标准 InputStreams 上工作。它不再抛出错误,但不知何故,它仍然跳过了比 3 级存档更深的嵌套 zip(仍然不确定它是否是正确的命名方法,哈哈)。对此的解决方案也很简单——我将ZipInputStream 包装到另一个ZipInputStream 时,将它反复传递给我的函数。代码如下:

private void processZipFile(ZipInputStream zipInputStream) throws IOException {
    ZipEntry zipEntry;
    while ((zipEntry = zipInputStream.getNextEntry()) != null) {
        System.out.println("    " + zipEntry.getName());
        if (zipEntry.getName().endsWith(".zip")) {
            processZipFile(new ZipInputStream(zipInputStream));
        } else if (zipEntry.getName().endsWith(".txt")) {
           //other things to todo...
        }
        //other things to todo...
    }

【问题讨论】:

  • 这里没有gzipnio。不要乱加标签。
  • 对不起,确实是我的错,和问题有关,严格来说不是问题!

标签: java zip zipinputstream


【解决方案1】:

代替

processZipFile(stream);

你需要使用

processZipFile(zipInputStream);

【讨论】:

  • 哇,没想到这一点,它确实有效,赞成你的答案@talex,但如果你能提供一些信息为什么它会以这种方式工作或至少阅读一些信息,我会将其标记为最佳来源,所以我和其他人将来可能会从中得到更多
  • zipInputStream 将您的数据解压缩,而stream 包含原始数据。
猜你喜欢
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
  • 2011-03-13
  • 1970-01-01
  • 2017-05-24
相关资源
最近更新 更多