如何在 Java 中创建未压缩的 Zip 存档
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1206970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create Uncompressed Zip archive in Java
提问by
I am using the Zip utility package of Java and wanted to know how to create a zip file with no compression at all. Setting the level to 0 doesn't help. Is this right?
我正在使用 Java 的 Zip 实用程序包,想知道如何创建一个完全没有压缩的 zip 文件。将级别设置为 0 没有帮助。这是正确的吗?
Also, when I used the STOREDmethod, it throws following exception:
此外,当我使用该STORED方法时,它会引发以下异常:
java.util.zip.ZipException: STORED entry missing size, compressed size, or crc-32
I can set the size but now following exception is thrown:
我可以设置大小,但现在抛出以下异常:
java.util.zip.ZipException: invalid entry crc-32
I am just following all the examples available by searching on the web and I am not able to really understand it properly I guess. It would be great if someone can help me on this and provide me suggestion to correct the problem I might be doing.
我只是通过在网上搜索来跟踪所有可用的示例,我猜我无法真正正确理解它。如果有人可以在这方面帮助我并为我提供纠正我可能正在做的问题的建议,那就太好了。
回答by PMorganCA
I'm leery of aperkinssolution (since deleted), but I know why it worked. The line (which has since been corrected in his answer)
我对aperkins解决方案持怀疑态度(因为被删除),但我知道它为什么有效。该行(此后已在他的回答中更正)
zipOut.setLevel(ZipOutputStream.STORED); // accidentally right
was using the static value ZipOutputStream.STORED, which coincidentally equals 0. So what that line is doing is setting the levelused by the default DEFLATED method to zero compression (this is obviously what you want to do, but happened to only work by luck). So to get what you want explicitly and safely, use this instead:
使用的是静态值ZipOutputStream.STORED,恰好等于0. 所以该行所做的是将默认 DEFLATED 方法使用的级别设置为零压缩(这显然是您想要做的,但碰巧只能靠运气)。因此,要明确且安全地获得您想要的内容,请改用以下代码:
zipOut.setMethod(ZipOutputStream.DEFLATED); // this line optional
zipOut.setLevel(0);
or
或者
zipOut.setLevel(Deflater.NO_COMPRESSION);
If you use
如果你使用
zipOut.setMethod(ZipOutputStream.STORED);
zipOut.setLevel(Deflater.NO_COMPRESSION);
you'll probably get the Exception that Keya noted in the original question. I believe Christian Schlichtherleis right; you are getting the Exceptions because you are not setting the CRC in the entry. The repercussions of that is that to use the STORED method, you have to read the entire entry file first, or find some other way to set the size, compressed size (must be equal) and the CRC before you call zipOut.putNextEntry(). Otherwise, you'll run into more exceptions if you overrun the size attribute by writing too many bytes to the output stream. It appears that the ZIP specs say that if you are writing STORED data then it has to write the header [which includes the CRC-32 and length] "up front" before the data itself, hence the java API requiring these be set before it can start, since it basically only supports streaming out to the final zip file.
您可能会得到 Keya 在原始问题中指出的异常。我相信Christian Schlichtherle是对的;您收到异常是因为您没有在条目中设置 CRC。这样做的后果是,要使用STORED方法,你必须先读取整个入口文件,或者在调用之前找到其他方法设置大小、压缩大小(必须相等)和CRCzipOut.putNextEntry(). 否则,如果通过将太多字节写入输出流来超出 size 属性,则会遇到更多异常。似乎 ZIP 规范说,如果您正在写入 STORED 数据,那么它必须在数据本身之前“预先”写入标头 [包括 CRC-32 和长度],因此 Java API 要求在它之前设置这些可以开始了,因为它基本上只支持流输出到最终的 zip 文件。
回答by Christian Schlichtherle
You need to use the STOREDmethod, but this requires that you set the size, compressedSizeand crc32properties of the corresponding ZipEntrybefore you can call putNextEntryon the ZipOutputStream. You can precompute the CRC-32 by using a Crc32OutputStream.
您需要使用的STORED方法,但是这需要您设置的size,compressedSize并且crc32相应的属性ZipEntry后,才能调用putNextEntry上ZipOutputStream。您可以使用Crc32OutputStream.
回答by Li Ying
FYI:
供参考:
In JDK Source of the method [java.util.zip.ZipOutputStream.setLevel(int)]:
在方法[java.util.zip.ZipOutputStream.setLevel(int)]的JDK Source中:
public void setLevel(int level) {
def.setLevel(level);
}
It simply redirect the compression level setting to the field variable [def], which is an instance of [java.util.zip.Deflater].
它只是将压缩级别设置重定向到字段变量 [def],它是 [java.util.zip.Deflater] 的一个实例。
And in the source code of the class [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;
So, I think it will be more readable if you use the constant value [Deflater.NO_COMPRESSION]:
所以,我认为如果你使用常量值 [Deflater.NO_COMPRESSION] 会更易读:
zipOut.setMethod(ZipOutputStream.DEFLATED);
zipOut.setLevel(Deflater.NO_COMPRESSION);

