代码之家  ›  专栏  ›  技术社区  ›  Kico Lobo

如何检查生成的zip文件是否已损坏?

  •  23
  • Kico Lobo  · 技术社区  · 16 年前

    我们有一段代码可以在系统上生成一个zip文件。一切正常,但有时这个用filzip或winzip打开的zip文件被认为已损坏。

    所以,我的问题是:如果生成的zip文件被破坏,我们如何通过编程检查?

    下面是我们用来生成zip文件的代码:

    try {
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(tmpFile));
        byte[] buffer = new byte[16384];
        int contador = -1;
        for (DigitalFile digitalFile : document.getDigitalFiles().getContent()) {
           ZipEntry entry = new ZipEntry(digitalFile.getName());
           FileInputStream fis = new FileInputStream(digitalFile.getFile());
           try {
              zos.putNextEntry(entry);
              while ((counter = fis.read(buffer)) != -1) {
                 zos.write(buffer, 0, counter);
              }
              fis.close();
              zos.closeEntry();
           } catch (IOException ex) {
              throw new OurException("It was not possible to read this file " + arquivo.getId());
           }
        }
        try {
          zos.close();
        } catch (IOException ex) {
          throw new OurException("We couldn't close this stream", ex);
        }
    

    我们这里有什么不对的地方吗?

    编辑: 实际上,上面的代码是完全正确的。我的问题是我为我的用户重定向了错误的流。所以,他们不是打开一个zip文件,而是打开完全不同的东西。我的错:(

    但主要问题仍然是: 如何通过编程验证给定的zip文件是否未损坏?

    8 回复  |  直到 11 年前
        1
  •  27
  •   Jean-François Savard    11 年前

    你可以使用 ZipFile 类以检查文件:

     static boolean isValid(final File file) {
        ZipFile zipfile = null;
        try {
            zipfile = new ZipFile(file);
            return true;
        } catch (IOException e) {
            return false;
        } finally {
            try {
                if (zipfile != null) {
                    zipfile.close();
                    zipfile = null;
                }
            } catch (IOException e) {
            }
        }
    }
    
        2
  •  9
  •   Nikhil Das Nomula    13 年前

    我知道发布这个消息已经有一段时间了,我使用了你们所有人提供的代码,并想出了这个。这对实际问题很有用。检查zip文件是否损坏

    private boolean isValid(File file) {
        ZipFile zipfile = null;
        ZipInputStream zis = null;
        try {
            zipfile = new ZipFile(file);
            zis = new ZipInputStream(new FileInputStream(file));
            ZipEntry ze = zis.getNextEntry();
            if(ze == null) {
                return false;
            }
            while(ze != null) {
                // if it throws an exception fetching any of the following then we know the file is corrupted.
                zipfile.getInputStream(ze);
                ze.getCrc();
                ze.getCompressedSize();
                ze.getName();
                ze = zis.getNextEntry();
            } 
            return true;
        } catch (ZipException e) {
            return false;
        } catch (IOException e) {
            return false;
        } finally {
            try {
                if (zipfile != null) {
                    zipfile.close();
                    zipfile = null;
                }
            } catch (IOException e) {
                return false;
            } try {
                if (zis != null) {
                    zis.close();
                    zis = null;
                }
            } catch (IOException e) {
                return false;
            }
    
        }
    }
    
        3
  •  3
  •   John Doe    16 年前

    我认为您将在生成zip文件期间看到相应的异常堆栈跟踪。所以,您可能不想增强异常处理。

        4
  •  2
  •   Sören    15 年前

    在我的实现中,它看起来是这样的。也许它能帮助你:

    //[...]
    
    try {
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
    
        zos.putNextEntry(new ZipEntry(file.getName()));
    
        try {
            final byte[] buf = new byte[BUFFER_SIZE];
            while (true) {
                final int len = bis.read(buf);
                if (len == -1) {
                    break;
                }
                zos.write(buf, 0, len);
            }
            zos.flush();
            zos.closeEntry();
        } finally {
            try {
                bis.close();
            } catch (IOException e) {
                LOG.debug("Buffered Stream closing failed");
            } finally {
                fis.close();
            }
        }
    } catch (IOException e) {
        throw new Exception(e);
    }
    
    //[...]
    zos.close
    
        5
  •  1
  •   Waverick    16 年前

    也许交换以下两行?;

    fis.close();
    zos.closeEntry();
    

    我可以想象closeEntry()仍然会从流中读取一些数据。

        6
  •  1
  •   stacker    16 年前

    您的代码基本上是正常的,请尝试找出哪个文件对损坏的zip文件负责。检查digitalfile.getfile()是否始终向fileinputstream返回有效且可访问的参数。只需在代码中添加一点日志记录,您就会发现哪里出了问题。

        7
  •  1
  •   Community Mohan Dere    9 年前
    new ZipFile(file) 
    

    再次压缩文件,这样重复的工作,这不是您要找的。尽管只检查一个文件,但问题是压缩n个文件。

    看看这个: http://www.kodejava.org/examples/336.html

    为zip创建校验和:

    CheckedOutputStream checksum = new CheckedOutputStream(fos, new CRC32());
    ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(checksum));
    ...
    

    当你完成压缩后,展示它

    System.out.println("Checksum   : " + checksum.getChecksum().getValue());
    

    您必须用Java或其他工具读取zip,检查校验和是否匹配。

    看见 https://stackoverflow.com/a/10689488/848072 更多信息

        8
  •  0
  •   user7094    16 年前

    ZIPOUT流 does not close 底层流。

    你需要做的是:

    FileOutputStream fos = new FileOutputStream(...);
    ZipOutputStream zos = new ZipOutputStream(fos);
    

    然后在你的封闭区:

    zos.close();
    fos.flush(); // Can't remember whether this is necessary off the top of my head!
    fos.close();