为什么我收到复制的 zips 错误 "start of central directory not found"

Why am I receiving the error "start of central directory not found" for copied zips

我在内存中递归解压缩 zip 文件,读取内容并将其注入任何找到的占位符,然后再次打包它们并创建输出文件。

这里是有问题的方法:

public void unpackZipFile(InputStream in, OutputStream out) throws IOException {
    ZipInputStream zin = new ZipInputStream(in);
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    ZipOutputStream zos = new ZipOutputStream(bout);
    for (ZipEntry entry = zin.getNextEntry(); entry != null; entry = zin.getNextEntry()) {
        if (entry.isDirectory() || entry.getName().startsWith("__MACOSX/")) continue;
        zos.putNextEntry(new ZipEntry(entry.getName()));
        processInputStream(zin, zos);
        zos.closeEntry();
    }
    zos.close();
    bout.writeTo(out);
}

不幸的是,大多数 zip 解压器都在抱怨生成的文件。 这方面的一个例子是:

warning [1-master.zip.data]:  1198 extra bytes at beginning or within zipfile
(attempting to process anyway)
error [1-master.zip.data]:  start of central directory not found;
zipfile corrupt.
(please check that you have transferred or created the zipfile in the
appropriate BINARY mode and that you have compiled UnZip properly)

然而,没有抱怨的解压器产生的正是预期的结果。 None 个文件似乎已损坏,内容符合预期,运行 符合预期。似乎唯一受影响的文件是 zip 本身,无论它们是最外层的 zip 还是嵌套的,它们都有这个问题。

在过去的几天里,我一直在尝试找出问题所在,但运气不佳,我想新的一双眼睛可能有助于揭示我的无知。

编辑:整个class:https://gist.github.com/justisr/0b127182fb143c06a1888f83a628995f

Justis 提供的 class 文件让我们知道这里出了什么问题。

https://gist.github.com/justisr/0b127182fb143c06a1888f83a628995f

public void processInputStream(String loc, InputStream in, OutputStream out) throws IOException {
    if (processLocation(loc)) {
        switch (parseFormat((PushbackInputStream) (in = new PushbackInputStream(in, 8)))) {
        case CLASS:
            processClassFile(loc, in, out);
            break;
        case EMPTY_OBJECT:
            copy(in, out);
            break;
        case OTHER:
            copyReplace(in, out, loc);
            break;
        case RAR:
            copy(in, out);
            break;
        case ZIP_OR_JAR:
            unpackZipFile(loc, in, out);
            break;
        case SCHEMATIC:
            break;
        case PNG:
            break;
        }
    }
    //<-- valid ZIP within output stream to this point
    copy(in, out);
}

对于导致此问题的特定 ZIP 文件,unneeded/arbitrary 数据位于文件末尾,ZipInputStream 知道要忽略它,并且对 .read() 的任何调用都将 return -读取 1 个字节。

但是,这个对 copy() 的外部调用是在基本输入和输出流之间,读取和写入这个 unneeded/arbitrary 数据,因此破坏了 ZIP 文件。

知道这是使用默认情况并删除对 copy() 的外部调用以确保不会将不需要的数据直接写入输出流的明显修复。