我正在使用Java的Zip实用程序包,并想知道如何创建一个没有压缩的zip文件。将级别设置为0无济于事。这是对的吗?
此外,当我使用STORED
方法时,它会引发以下异常:
java.util.zip.ZipException: STORED entry missing size, compressed size, or crc-32
我可以设置大小,但现在抛出异常:
java.util.zip.ZipException: invalid entry crc-32
我只是通过在网上搜索来关注所有可用的示例,我猜我无法正确理解它。如果有人可以帮助我,并提供我纠正我可能正在做的问题的建议,那将是很棒的。
答案 0 :(得分:12)
我对 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在原始问题中提到的异常。我相信 Christian Schlichtherle 是正确的;您正在获取例外,因为您没有在条目中设置CRC。这种情况的后果是,要使用STORED方法,您必须首先读取整个条目文件,或者在调用zipOut.putNextEntry()
之前找到一些其他方法来设置大小,压缩大小(必须相等)和CRC 。否则,如果通过向输出流写入太多字节来超出size属性,则会遇到更多异常。似乎ZIP规范说如果你正在编写STORED数据,那么它必须在数据本身之前编写头文件[包括CRC-32和长度],因此需要在它之前设置java API。可以启动,因为它基本上只支持流式传输到最终的zip文件。
答案 1 :(得分:7)
您需要使用STORED
方法,但这需要您先设置相应size
的{{1}},compressedSize
和crc32
属性可以在ZipEntry
上致电putNextEntry
。您可以使用ZipOutputStream
预先计算CRC-32。
答案 2 :(得分:5)
供参考:
在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);