簡體   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