ZipFile 抛出错误,但是 ZipInputStream 可以解压缩存档。

7
我在使用 java.util.zip.* 时遇到了一个奇怪的问题。
我有一个zip文件,当进行解压缩时,出现以下情况:
ZipFile zipfile = new ZipFile(file, ZipFile.OPEN_READ);

这是确切的错误信息

java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:127)
at java.util.zip.ZipFile.<init>(ZipFile.java:143)
at com.basware.ExtractZip.unpack(ExtractZip.java:27)
at com.basware.ExtractZip.main(ExtractZip.java:17)

但是如果我使用以下代码,就能够打开归档文件而不出现任何错误。
try {
     BufferedOutputStream dest = null;       
     File file = new File("File_Path");        
     FileInputStream fis = new FileInputStream(file);
     ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
     ZipEntry entry;
     while((entry = zis.getNextEntry()) != null) {
        System.out.println("Extracting: " +entry);
        int count;
        byte data[] = new byte[BUFFER];
        // write the files to the disk
        FileOutputStream fos = new 
      FileOutputStream(entry.getName());
        dest = new 
          BufferedOutputStream(fos, BUFFER);
        while ((count = zis.read(data, 0, BUFFER)) 
          != -1) {
           dest.write(data, 0, count);
        }
        dest.flush();
        dest.close();
     }
     zis.close();

请注意,文件使用WinZIP进行压缩。
我的问题是,既然ZipFile和ZipInputStream几乎是一样的,为什么ZipFile会抛出异常,无法进行解压缩。
编辑:问题在于,如果我使用WinZip工具压缩文件,然后使用列出的程序解压缩,它能正常工作。但是,这个问题特别针对来自外部来源的存档(外部来源声称他们正在使用WinZip)。此外,如果我使用WinZip工具打开完全相同的存档(外部存档),它会显示并解压缩文件。但这个JAVA特定代码(ZipFile)根本不起作用。
编辑:我无法弄清楚为什么Java本机代码不能处理我的ZIP存档,但是apache compress解决了我的问题。如Ian Roberts所建议的那样,它适合我。
2个回答

4
ZipFile试图解析zip文件末尾的“中央目录”,以建立一个数据结构,使您能够通过名称访问单个条目。而ZipInputStream则不会这样做,它只查看每个条目的本地标头,因为它从顶部向底部读取文件。因此,看起来您的文件具有良好的条目,但由于某种原因中央目录损坏。

有许多可能性,例如条目名称中非ASCII字符的编码问题,或者如果zip文件包含超过64k个条目。我建议尝试使用commons-compress实现的ZipFile -即使它不能工作,也应该比您从java.util.zip获得的“出错了”更具体的错误消息。


1
@C4CodeE4Exe 这就是 Java 中部分本地 zip 实现的问题之一,它的错误信息并不是很有帮助... 我已经添加了一些更多的想法。 - Ian Roberts
我尝试使用org.apache.commons.compress.archivers.zip.ZipFile,它能够显示条目,而不是错误。但是有一些异常情况- 没有getName方法,entries已被重命名为getEntries,getEntries和getEntry返回org.apache.commons.compress.archivers.zip.ZipArchiveEntry实例,close允许抛出IOException。 - C4CodeE4Exe

0
除了Ian Robert的回答之外,如果您可以使用Java 7,您可能希望避开旧的java.util.zip库,而是使用ZIP文件系统提供程序

抱歉,我们没有使用Java 7。 - C4CodeE4Exe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接