我正在开发一个 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 的根本原因。 实现一个解决方案,允许我的代码自动打开、修复和处理文件。 有没有人遇到过类似的问题或对如何解决这个问题有任何建议?任何帮助或指示将不胜感激。
谢谢!
XLSX 文件是压缩的 XML 文件。 因此,如果您重命名后缀 xlsx -> zip,您可以在 Winzip 或其他 zip 软件中打开它并查看文件的内容。 您还可以使用该程序来找出一些事实,例如格式(Zip64 等),也许其中的文件有一个 0 字节条目,而它应该填充更多数据(就像它说的 0 字节,但其中有实际字节)文件)。 这就是错误消息似乎表明的内容。 您需要开始收集有关该文件的事实,这可能有助于您了解它的问题所在。
您可能也遇到过这个错误:
Stream Zip 文件:java.util.zip.ZipException:条目大小无效(预期为 0,但实际为 419 字节)
4GB 以下的 Zip64 文件有时会遇到此缺陷,因此请检查该 zip 文件是否可能是 zip64。 并查看您使用的 JDK 版本。 Java8 的一些版本容易受到此错误的影响,而另一些则不会。
这一切都取决于该 zip 文件的结构,因此您必须深入研究文件格式的细节才能弄清楚。