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

我正在开发一个项目,该项目需要读取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.(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实例时会出现这个问题。

当我将数据写入文件时,我喜欢这样(使用exception和关闭的练习规则):

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

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

  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

我找到的解决方案,我一直在寻找一段时间,是为了确保你不打开你用来打开FileOutputStream以保存Workbook WorkbookFileWorkbook 。 而是,使用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读取时的方法(尝试/ catch /最后省略了可读性):

 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上面的评论帮助我今天解决了这个问题(使用输入和输出的不同文件路径)。 谢谢!