繁体   English   中英

Apache-POI:无法写入现有工作簿

[英]Apache-POI: Unable to write to an existing workbook

我正在处理一个项目,该项目需要读取 Excel 工作簿、调用必要的 Web 服务,然后从 Web 服务获取响应并将该信息输入到读取的同一个 Excel 工作簿中。

这是我在尝试写入 Excel 工作簿时看到的错误:

Exception in thread "main" org.apache.poi.POIXMLException: java.io.IOException: Can't obtain the input stream from /docProps/app.xml
at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:141)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:177)
at ext.ExcelProcessor.main(ExcelProcessor.java:197)
Caused by: java.io.IOException: Can't obtain the input stream from /docProps/app.xml
    at org.apache.poi.openxml4j.opc.PackagePart.getInputStream(PackagePart.java:500)
    at org.apache.poi.POIXMLProperties.<init>(POIXMLProperties.java:75)
    at org.apache.poi.POIXMLDocument.getProperties(POIXMLDocument.java:139)
    ... 2 more

这是我打开文件/阅读的代码:

pkg = OPCPackage.open(xslFile);
    theWorkbook = new XSSFWorkbook(pkg);

在此之后,我读取每一行并提取每个单元格值。

完成此操作后,我将在 Success 和 Result Message 的标题下创建单元格,然后执行以下操作:

String sessionData = sessionKey[1];
                String[] cellValCurrRow = rowCellVals.get(r-1);
                String attachmentData[] = WQSServices.uploadAttachment(sessionData, cellValCurrRow);

                XSSFCell cell = xslRows[r].getCell(7);

                if(cell == null)
                {
                    cell = xslRows[r].createCell(7);
                }

                System.out.println("The Cell: "+cell.getStringCellValue());

                XSSFCell cell2 = xslRows[r].getCell(8);

                if(cell2 == null)
                {
                    cell2 = xslRows[r].createCell(8);
                }

                System.out.println("The Cell: "+cell2.getStringCellValue());

                cell.setCellType(Cell.CELL_TYPE_STRING);
                cell2.setCellType(Cell.CELL_TYPE_STRING);
                cell.setCellValue(attachmentData[0]);
                cell2.setCellValue(attachmentData[1]);

                System.out.println("New Cell Data: 1-"+cell.getStringCellValue()+" 2-"+cell2.getStringCellValue());

                FileOutputStream fos = new FileOutputStream(xslFile);
                theWorkbook.write(fos);
                fos.close();

有没有人遇到过类似的问题?

我收到了相同的错误消息,但使用了不同的类。 我使用的当前 poi 版本是 poi-ooxml 3.9 但它仍然存在问题。 现在我解决了我的问题,我认为当您首先获得 Workbook 实例时会出现这个问题。

当我将数据写入文件时,我喜欢这样(有例外和关闭的实践规则):

    FileOutputStream fos = new FileOutputStream(filePath);
    wb.write(fos);
    fos.close();

当我像这样获取 Workbook 实例时,我收到“无法从 /docProps/app.xml 获取输入流”错误消息:

    Workbook wb = WorkbookFactory.create(new File(filePath));

当我解决问题时,修改后的代码是

    Workbook wb = WorkbookFactory.create(new FileInputStream(filePath));

就我而言,无论您是打开、读取和写入同一个文件,还是从一个文件读取然后写入另一个文件,都无关紧要。 如果您阅读 poi 源代码,您会看到我使用的工厂方法可能会调用 OPCPackage 类中的 open() 方法。 尝试使用获取 InputStream 作为其参数的方法。

我认为这里的问题是您使用相同的 filePath xslFile打开和保存文件。

打开文件,

pkg = OPCPackage.open(xslFile);
    theWorkbook = new XSSFWorkbook(pkg);

保存文件,

FileOutputStream fos = new FileOutputStream(xslFile);
theWorkbook.write(fos);
fos.close();

您需要一个 InputStream 来读取和处理您的文件,但是当您在相同的路径和文件名下创建一个 OutputStream 时,此流变得无法访问。

列出的当前问题是自 2010 年以来一直存在的错误,可以在 @ https://issues.apache.org/bugzilla/show_bug.cgi?id=49940 中找到

在下面的 stackoverflow 列表中,发现了一种解决方法,如果您在对文件进行另一次写出之前再次关闭并重新打开这本书,它将毫无问题地工作。 这无论如何都不是很有效,但它确实可以解决问题,直到 Apache-POI 开发团队找出问题为止。

https://stackoverflow.com/a/9792406/1231715

该解决方案,我发现这一点,我一直在寻找了一段时间,是确保你不打开WorkbookFile您可以使用它打开FileOutputStream保存Workbook 相反,使用FileInputStream打开Workbook

像这样的东西将完美无缺地工作

        File inputFile = new File("Your-Path");
        this.inputStream = new FileInputStream(inputFile);
        this.opc = OPCPackage.open(this.inputStream);
        this.workbook = WorkbookFactory.create(opc);

...

        this.outputStream = new FileOutputStream(inputFile);
        this.workbook.write(this,outputStream);

不要忘记关闭每个打开的流和OPCPackage

以下是使用 OPCPackage 读取时如何做到这一点(为了可读性,try/catch/finally 省略):

OPCPackage pkg = OPCPackage.open("existingFile.xlsx");
XSSFWorkbook wb = (XSSFWorkbook) WorkbookFactory.create(pkg);

进行修改... XSSFSheet sheet = wb.getSheetAt(0); ...

fos = new FileOutputStream("outputFileName.xlsx");
wb.write(fos);
pkg.close();
fos.close();
Faces.sendFile(new File(outputFileName)

上面来自 Jayamohan 的评论帮助我解决了今天的这个问题(对输入和输出使用不同的文件路径)。 谢谢!

确保在关闭之前再次打开相同的文件。

FileInputStream file1 = new FileInputStream("file.xlsx");
FileOutputStream file2 = new FileOutputStream("file.xlsx");
file2.close();
file1.close();

此代码将引发此错误。

解决方案:

FileInputStream file1 = new FileInputStream("file.xlsx");
file1.close();
FileOutputStream file2 = new FileOutputStream("file.xlsx");
file2.close();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM