簡體   English   中英

使用Apache POI修改現有的xlsx電子表格會導致無法讀取的內容錯誤

[英]Modifying existing xlsx spreadsheet using Apache POI leads to unreadable content error

因此,使用Apache POI在Excel中出現不可讀內容錯誤的主題似乎很常見。 然而,我很驚訝我仍然找不到我的問題的一個例子,特別是因為我想要做的事情似乎非常簡單。 這讓我相信一些東西可能只是我對一些java對象的理解,特別是File和FileInputStream。 我通過大量的試驗和錯誤發現了如何讓它發揮作用,但我的問題是為什么一個有用,為什么另一個沒有,並且想要了解潛在的問題。 我認為也可以幫助其他人理解。 這正是我想要做的:

打開現有的xlsx文件,向其中添加工作表,並將其保存為與其原始文件相同的文件名。 實質上,只需修改現有的xlsx文件即可添加工作表。

下面是不起作用的代碼,以及執行的代碼,我想知道為什么使用File對象不起作用。在這兩個示例中,我已經使用名為Voucher_1的工作表創建了TravelVouchers.xlsx文件,它可以正常工作很好打開它。

以下代碼導致travelVouchersWkBk.write(fileOut);上出現NullPointerException travelVouchersWkBk.write(fileOut); 線:

File travelVouchersFile = new File("./Output/TravelVouchers.xlsx");
Workbook travelVouchersWkBk = WorkbookFactory.create(travelVouchersFile);
travelVouchersWkBk.createSheet("Voucher_2");
FileOutputStream fileOut = new FileOutputStream(travelVouchersFile);
travelVouchersWkBk.write(fileOut);
fileOut.flush();
fileOut.close();

雖然以下代碼很有效:

File travelVouchersFile = new File("./Output/TravelVouchers.xlsx");
FileInputStream fileIn = new FileInputStream(travelVouchersFile);
Workbook travelVouchersWkBk = WorkbookFactory.create(fileIn);
travelVouchersWkBk.createSheet("Voucher_2");
fileIn.close();
FileOutputStream fileOut = new FileOutputStream(travelVouchersFile);
travelVouchersWkBk.write(fileOut);
fileOut.flush();
fileOut.close();

在不起作用的代碼中,它會導致excel中出現無法讀取內容的錯誤,當我選擇修復時,我可以打開它,它只有Voucher_1。 顯然使用WorkbookFactory.create和File對象不起作用,使用FileInputStream的情況不行,但我想知道我對File vs FileInputStream的理解與此問題有關。

非常感謝您的澄清,我真的很感激! 保羅

我相信使用FileWorkbookFactory用於讀取Workbook 然后寫入同一 Workbook - File是不是一個好主意,直到如今。 apache POI文檔提到:

文件與InputStreams

打開工作簿(.xls HSSFWorkbook或.xlsx XSSFWorkbook)時,可以從File或InputStream加載工作簿。 使用File對象可以降低內存消耗,而InputStream需要更多內存,因為它必須緩沖整個文件。

但是為什么使用File對象可以降低內存消耗? 這是因為Workbookfactory然后創建一個RandomAccessFile ,它不需要在內存中完全讀取。 要驗證請閱讀WorkbookFactory.java的來源 - > public static Workbook create(File file, String password, boolean readOnly)NPOIFSFileSystem.java - > private NPOIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError)FileBackedDataSource.java - > private static RandomAccessFile newSrcFile(File file, String mode)

但據我所知,沒有可能訪問此RandomAccessFile 所以我們不能寫它,也不能關閉它而不關閉整個Workbook 因此,在上面的示例中,當Workbook.write(FileOutputStream)嘗試編寫文件時,將打開RandomAccessFile進行讀寫(rw模式)。

因此,使用File可能適合只讀或從一個文件讀取並保存到另一個文件。 但是直到現在,使用File來讀取和寫入同一個文件並不是一個好主意。 對於這個FileInputStreamFileOutputStream更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM