如何在Java中创建Uncompressed Zip存档

我正在使用Java的Zip实用程序包,并想知道如何创建一个没有压缩的zip文件。 将级别设置为0无济于事。 这是正确的吗?

此外,当我使用STORED方法时,它抛出以下exception:

 java.util.zip.ZipException: STORED entry missing size, compressed size, or crc-32 

我可以设置大小,但现在抛出以下exception:

 java.util.zip.ZipException: invalid entry crc-32 

我只是通过在网上搜索来关注所有可用的例子,我猜我无法正确理解它。 如果有人可以帮助我并提供我纠正我可能正在做的问题的建议,那将是很棒的。

我对aperkins解决方案持怀疑态度(自删除以来),但我知道它为何有效。 这条线(后来在他的回答中得到纠正)

 zipOut.setLevel(ZipOutputStream.STORED); // accidentally right 

使用静态值ZipOutputStream.STORED ,巧合地等于0 。 那么该行正在做的是将默认DEFLATED方法使用的级别设置为零压缩(这显然是你想要做的,但碰巧只能运气)。 因此,要明确安全地获得您想要的内容,请使用以下内容:

 zipOut.setMethod(ZipOutputStream.DEFLATED); // this line optional zipOut.setLevel(0); 

要么

 zipOut.setLevel(Deflater.NO_COMPRESSION); 

如果你使用

 zipOut.setMethod(ZipOutputStream.STORED); zipOut.setLevel(Deflater.NO_COMPRESSION); 

你可能会得到Keya在原始问题中提到的exception。 我相信Christian Schlichtherle是对的; 您正在获取例外,因为您没有在条目中设置CRC。 这样的影响是,要使用STORED方法,您必须首先读取整个条目文件,或者在调用zipOut.putNextEntry()之前找到一些其他方法来设置大小,压缩大小(必须相等)和CRC 。 否则,如果通过向输出流写入太多字节来超出size属性,则会遇到更多exception。 似乎ZIP规范说如果您正在编写STORED数据,那么它必须在数据本身之前将“包含CRC-32和长度”的头部“预先”写入,因此需要在其之前设置的Java API可以启动,因为它基本上只支持流式传输到最终的zip文件。

您需要使用STORED方法,但这需要您在putNextEntry上调用putNextEntry之前设置相应ZipEntrysizecompressedSizecrc32属性。 您可以使用Crc32OutputStream预先计算CRC-32。

供参考:

在JDK方法的源代码[java.util.zip.ZipOutputStream.setLevel(int)]中:

 public void setLevel(int level) { def.setLevel(level); } 

它只是将压缩级别设置重定向到字段变量[def],它是[java.util.zip.Deflater]的一个实例。

并在类[java.util.zip.Deflater]的源代码中:

 /** * Compression level for no compression. */ public static final int NO_COMPRESSION = 0; /** * Compression level for fastest compression. */ public static final int BEST_SPEED = 1; /** * Compression level for best compression. */ public static final int BEST_COMPRESSION = 9; /** * Default compression level. */ public static final int DEFAULT_COMPRESSION = -1; 

所以,如果你使用常量值[Deflater.NO_COMPRESSION],我认为它会更具可读性:

 zipOut.setMethod(ZipOutputStream.DEFLATED); zipOut.setLevel(Deflater.NO_COMPRESSION); 
Interesting Posts