java.io.IOException:尝试使用 Apache POI 打开 Excel 文件时无法读取 zip 条目源

问题描述 投票:0回答:1

我正在开发一个 Groovy 项目,我需要使用 Apache POI 加载 Excel 文件。该文件是由第三方提供的,我在尝试直接打开它时遇到问题。如果我在 Excel 中手动打开文件并保存它,该文件将变得可用,但我想在我的代码中自动执行此过程。

    java.io.IOException: Failed to read zip entry source
  at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:103)
  at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:324)
  at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:185)
  at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:144)
  at com.apsec.groovy.job.util.POIUtil.openWorkbook(POIUtil.groovy:60)
  at com.apsec.groovy.job.axiom.AxiomAToMReportV2Load.run(AxiomAToMReportV2Load.groovy:213)
  at com.apsec.groovy.job.AbstractJob.run(AbstractJob.groovy:67)
  at com.apsec.groovy.job.developer.LocalEnvironment.run(LocalEnvironment.groovy:106)
  at com.apsec.groovy.job.axiom.AxiomAToMReportV2Load.main(AxiomAToMReportV2Load.groovy:359)
Caused by: java.util.zip.ZipException: invalid entry size (expected 0 but got 1053 bytes)
  at java.util.zip.ZipInputStream.readEnd(ZipInputStream.java:384)
  at java.util.zip.ZipInputStream.read(ZipInputStream.java:196)
  at org.apache.poi.openxml4j.util.ZipSecureFile$ThresholdInputStream.read(ZipSecureFile.java:219)
  at java.io.FilterInputStream.read(FilterInputStream.java:107)
  at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource$FakeZipEntry.<init>(ZipInputStreamZipEntrySource.java:132)
  at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:56)
  at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:100)
  ... 8 more

我正在使用 Apache POI 版本 3.16。

这是我正在使用的 openWorkbook 方法:

import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.usermodel.WorkbookFactory
import org.apache.poi.openxml4j.util.ZipSecureFile
import org.apache.poi.openxml4j.exceptions.InvalidFormatException
import groovy.util.logging.Slf4j
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.FileNotFoundException

@Slf4j
static Workbook openAndRepairWorkbook(File file) throws FileNotFoundException, IOException, InvalidFormatException {
    FileInputStream fis = null
    Workbook workbook = null
    File repairedFile = new File(file.getParent(), "repaired_" + file.getName())

    try {
        if (!file.exists() || !file.canRead()) {
            log.error("File does not exist or cannot be read: {}", file.getAbsolutePath())
            throw new FileNotFoundException("File does not exist or cannot be read: " + file.getAbsolutePath())
        }

        log.info("Attempting to open workbook from file: {}", file.getAbsolutePath())
        fis = new FileInputStream(file)
        ZipSecureFile.setMinInflateRatio(0.0001) // Adjust the zip bomb detection threshold

        try {
            workbook = WorkbookFactory.create(fis)
            log.info("Workbook successfully opened.")

            // Save the workbook to a new file to "repair" it
            log.info("Saving workbook to repaired file: {}", repairedFile.getAbsolutePath())
            FileOutputStream fos = new FileOutputStream(repairedFile)
            workbook.write(fos)
            fos.close()
            workbook.close()

            // Reopen the repaired file
            log.info("Reopening the repaired workbook.")
            fis = new FileInputStream(repairedFile)
            workbook = WorkbookFactory.create(fis)
            log.info("Repaired workbook successfully opened.")
        } catch (InvalidFormatException e) {
            log.error("InvalidFormatException encountered: {}", e.getMessage())
            throw e
        } catch (IOException e) {
            log.error("IOException encountered: {}", e.getMessage())
            throw e
        }
    } finally {
        if (fis != null) {
            try {
                fis.close()
            } catch (IOException e) {
                log.error("Error closing FileInputStream: {}", e.getMessage())
            }
        }
    }
    return workbook
}

我尝试过的

手动修复:

如果我在 Microsoft Excel 中打开有问题的 Excel 文件并简单地保存它而不进行任何更改,则我的代码可以毫无问题地处理该文件。 程序化尝试:

我尝试以编程方式模拟手动过程,方法是打开工作簿,将其保存到新文件,然后使用上面显示的 openAndRepairWorkbook 方法重新打开修复的文件。但是,我仍然遇到同样的错误。 我需要的 我想找到一种方法以编程方式处理此问题,而无需在 Excel 中手动打开和保存文件。理想情况下,我想:

确定与 zip 条目源相关的 IOException 的根本原因。 实现一个解决方案,允许我的代码自动打开、修复和处理文件。 有没有人遇到过类似的问题或对如何解决这个问题有任何建议?任何帮助或指示将不胜感激。

谢谢!

java excel groovy apache-poi ioexception
1个回答
0
投票

XLSX 文件是压缩的 XML 文件。 因此,如果您重命名后缀 xlsx -> zip,您可以在 Winzip 或其他 zip 软件中打开它并查看文件的内容。 您还可以使用该程序来找出一些事实,例如格式(Zip64 等),也许其中的文件有一个 0 字节条目,而它应该填充更多数据(就像它说的 0 字节,但其中有实际字节)文件)。 这就是错误消息似乎表明的内容。 您需要开始收集有关该文件的事实,这可能有助于您了解它的问题所在。

您可能也遇到过这个错误:

Stream Zip 文件:java.util.zip.ZipException:条目大小无效(预期为 0,但实际为 419 字节)

4GB 以下的 Zip64 文件有时会遇到此缺陷,因此请检查该 zip 文件是否可能是 zip64。 并查看您使用的 JDK 版本。 Java8 的一些版本容易受到此错误的影响,而另一些则不会。

这一切都取决于该 zip 文件的结构,因此您必须深入研究文件格式的细节才能弄清楚。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.