0

我在通过zip4j.

我可以使用以下代码生成 ZIP 存档(我省略了一些与问题无关的部分),这基本上取自zip4j教程:

File zipFile = new File(zipName);
ZipParameters params = new ZipParameters();
params.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
params.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
byte[] buffer = new byte[8192];
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
   for (/* loop through list of input data */) {
        String outputName = /* method to determine file name */;
        try (InputStream in = /* method to get IS */ ) {
            params.setFileNameInZip(outputName);
            File tmpEntry = new File(outputName);
            tmpEntry.createNewFile();
            out.putNextEntry(tmpEntry, params);
            int len;
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            tmpEntry.delete();
            out.closeEntry();
            in.close();
        }
    }
}

问题是虽然所有文件都正确包含在 ZIP 存档中,但它们声明的文件大小为 0。我可以使用“哑”ZIP 阅读器(如内置 TotalCommander 的阅读器)解压缩它们,因为所有数据实际上都在这里,但更多“聪明的”程序(如 7zip)会产生 CRC 错误并拒绝打开它们,因为它们已损坏。

我会说我需要以某种方式声明文件大小(我绝对不会在我的代码片段中这样做),但我无法找到(可能很明显)解决方案。我已经用谷歌搜索了本机java.util.zip.ZipEntry有方法,但我在....setSize()中没有看到类似的东西zip4j

任何人都知道正确的方法吗?

4

1 回答 1

1

所以解决方案非常简单。只需将以下设置添加到ZipParameters

params.setSourceExternalStream(true);

我是怎么发现的?

我深入研究了代码,并在类的closeEntry()方法中找到了以下内容:CipherOutputStream.javazip4j

if (zipParameters.isSourceExternalStream()) {
    fileHeader.setUncompressedSize(totalBytesRead);
    if (localFileHeader.getUncompressedSize() != totalBytesRead) {
        localFileHeader.setUncompressedSize(totalBytesRead);
    }
}

这是唯一调用方法的地方setUncompressedSize()——这听起来与声明的文件大小有关。所以我开始怀疑并试图在我的代码中设置参数。它完成了这项工作。

吸取的教训是,这个使用示例zip4j是不正确的,因为它缺少关键的代码行。

于 2018-03-29T12:13:42.047 回答