【问题标题】:java extract zip Unexpected end of ZLIB input streamjava提取zip ZLIB输入流的意外结束
【发布时间】:2022-02-01 17:15:26
【问题描述】:

我正在创建一个程序,它会提取一个 zip,然后将文件插入数据库,但我经常会收到错误

java.lang.Exception: java.io.EOFException: Unexpected end of ZLIB input stream

我无法确定原因,因为提取代码与您可以在网络上找到的所有其他代码几乎相同。我的代码如下:

public void extract(String zipName, InputStream content) throws Exception {

    int BUFFER = 2048;

    //create the zipinputstream 
    ZipInputStream zis = new ZipInputStream(content);

    //Get the name of the zip
    String containerName = zipName;

    //container for the zip entry
    ZipEntry entry;

    // Process each entry
    while ((entry = zis.getNextEntry()) != null) {

        //get the entry file name
        String currentEntry = entry.getName();

        try {

                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                // establish buffer for writing file
                byte data[] = new byte[BUFFER];
                int currentByte;

                // read and write until last byte is encountered
                while ((currentByte = zis.read(data, 0, BUFFER)) != -1) {

                    baos.write(data, 0, currentByte);
                }

                baos.flush(); //flush the buffer 

                //this method inserts the file into the database
                insertZipEntry(baos.toByteArray());

                baos.close();

        } 
        catch (Exception e) {
            System.out.println("ERROR WITHIN ZIP " + containerName);
        }
    }
}

【问题讨论】:

  • • 您是否检查过您尝试处理的 ZIP 流(文件)是否有效(例如,unzip 可以解压)? • 请查明代码中实际引发异常的行。
  • 我可能记错了,但您不应该在处理完每个条目后关闭它吗?
  • 你应该在调用insertZipEntry()之前关闭包,我们的'currentByte'变量命名不当:应该是'count'或类似的。
  • 您能为您的问题选择一个最佳答案吗?

标签: java


【解决方案1】:

这可能是这个JVM bug (JVM-6519463)引起的

我之前在 1000 个随机创建的文档中遇到了大约一两个错误,我应用了建议的解决方案(捕获 EOFException 并且不对其进行任何处理)并且我没有更多错误。

【讨论】:

    【解决方案2】:

    我会说您偶尔会收到截断的 Zip 文件来处理。检查上游。

    【讨论】:

      【解决方案3】:

      我有同样的异常,问题出在压缩方法上(不是提取)。写入输出流后,我没有使用zos.closeEntity() 关闭 ZipOutputStream。没有它,压缩效果很好,但我在提取时遇到了异常。

      public static byte[] zip(String outputFilename, byte[] output) {
          try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
               ZipOutputStream zos = new ZipOutputStream(baos)) {
              zos.putNextEntry(new ZipEntry(outputFilename));
              zos.write(output, 0, output.length);            
              zos.closeEntry(); //this line must be here
              return baos.toByteArray();
          } catch (IOException e) {
              //catch exception
          }
      }
      

      【讨论】:

        【解决方案4】:

        永远不要尝试读取超过条目包含的字节数。调用 ZipEntry.getSize() 以获取条目的实际大小,然后使用此值来跟踪条目中剩余的字节数,同时从条目中读取。见下文:

        try{    
        
           ...
        
           int bytesLeft = (int)entry.getSize();
           while ( bytesLeft>0 && (currentByte=zis.read(data, 0, Math.min(BUFFER, bytesLeft))) != -1) {
             ...
          }
        
          ...
        
          }
        

        【讨论】:

        • 没必要。 ZipInputStream 会为您解决这些问题。
        • EJP: 但它失败了。但是,entry.getSize() 和 entry.getCompressedSize() 都为我返回 -1。
        • @Buffalo 它失败了,因为输入被截断了,而且这种技术不能也不可能解决这个问题。
        猜你喜欢
        • 1970-01-01
        • 2022-08-22
        • 2011-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-22
        • 1970-01-01
        相关资源
        最近更新 更多