zip4j生成所有文件的拉链' size = 0

时间:2018-03-29 09:39:23

标签: java zip zip4j

我在通过zip4j生成ZIP文件时遇到问题。

我可以使用以下代码生成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.我可以使用" dumb"解压缩它们。 ZIP阅读器(如内置的TotalCommander'),因为所有数据实际上都在这里,但更多"聪明"程序(如7zip)产生CRC错误并拒绝将它们打开为损坏。

我会说我需要以某种方式声明文件大小(我绝对不会在我的代码片段中这样做),但我无法找到(可能很明显的)解决方案。我用谷歌搜索了原住民java.util.zip.ZipEntry.setSize()方法,但我在zip4j中看不到这样的内容......

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

1 个答案:

答案 0 :(得分:1)

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

params.setSourceExternalStream(true);

我是如何找到的?

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

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

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

所吸取的教训是this example使用zip4j是不正确的,因为它缺少重要的代码行。