使用Apache POI修改现有的xlsx电子表格导致不可读的内容错误

所以在使用Apache POI的Excel中,不可读的内容错误的话题似乎很常见。 然而,我很惊讶,我仍然无法find我的问题的一个例子,特别是因为它似乎非常简单,我正在努力。 这导致我相信有些东西可能只是通过我对一些java对象的了解,特别是File和FileInputStream。 我通过大量的试验和错误发现了如何使它工作,但我的问题是为什么一个工作,为什么另一个不工作,并希望了解潜在的问题。 我认为这也可以帮助别人理解。 这正是我想要做的:

打开一个现有的xlsx文件,为其添加一个表单,并将其保存为与原始文件相同的文件名。 实质上,只需修改现有的xlsx文件即可添加工作表。

下面是不工作的代码,以及代码,我想知道为什么使用File对象不起作用。在这两个示例中,我已经创build了一个名为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中出现无法读取的内容,并且当我select修复时,我可以打开它,并且只有Voucher_1。 所以显然使用WorkbookFactory.create与File对象不起作用,在哪里使用FileInputStream呢,但我想知道我不了解File vs FileInputStream,因为它涉及到这个问题。

非常感谢您的澄清,我真的很感激! 保罗

我相信使用WorkbookFactoryFile读取Workbook 然后写入相同的 WorkbookFile是不是一个好主意,直​​到现在。 apache POI文档提到:

文件与InputStreams

打开工作簿时,可以使用.xls HSSFWorkbook或.xlsx XSSFWorkbook,可以从File或InputStream中加载工作簿。 使用File对象可以降低内存消耗,而InputStream需要更多的内存,因为它必须缓冲整个文件。

为什么使用File对象可以降低内存消耗? 这是因为Workbookfactory然后创build一个RandomAccessFile不需要在内存中完全读取。 要validation,请阅读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 。 所以我们不能写信给它,也不能在不closures整个Workbook情况下closures它。 所以在上面的例子中,随着Workbook.write(FileOutputStream)尝试写入文件, RandomAccessFile将被打开以进行读写(rw模式)。

所以使用File可能对于只读或者从一个文件读取并保存到另一个文件来说是好的。 但是直到现在,使用File读取和写入相同的文件并不是一个好主意。 对于这个FileInputStreamFileOutputStream更好。