因此,使用Apache POI的Excel中无法读取的内容错误主题似乎很常见。然而,我很惊讶我仍然找不到我的问题的一个例子,特别是因为我想要做的事情似乎非常简单。这让我相信一些东西可能只是我对一些java对象的理解,特别是File和FileInputStream。我通过大量的试验和错误发现了如何让它发挥作用,但我的问题是为什么一个有用,为什么另一个没有,并且想要了解潜在的问题。我认为也可以帮助其他人理解。这正是我想要做的:
打开现有的xlsx文件,向其中添加工作表,并将其保存为与原始文件相同的文件名。实质上,只需修改现有的xlsx文件即可添加工作表。
下面是不起作用的代码,以及执行的代码,我想知道为什么使用File对象不起作用。在这两个例子中,我已经创建了 TravelVouchers.xlsx 带有名为 Voucher_1 的工作表的文件,可以正常打开它。
以下代码导致travelVouchersWkBk.write(fileOut);
行上的NullPointerException:
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。所以很明显使用带有File对象的WorkbookFactory.create不起作用,使用FileInputStream的情况不行,但我想知道我对File vs FileInputStream的理解与此问题有关。
非常感谢您的澄清,我真的很感激! 保罗
答案 0 :(得分:3)
我相信使用File
与WorkbookFactory
阅读Workbook
和然后写入相同 {{1} } - Workbook
直到现在才是个好主意。 apache POI文档提到:
Files vs InputStreams
打开工作簿时,可以是.xls HSSFWorkbook,也可以是.xlsx XSSFWorkbook,可以从文件或文件加载工作簿 的InputStream。使用File对象可以降低内存消耗, 而InputStream需要更多内存,因为它必须缓冲 整个文件。
但为什么使用File对象可以降低内存消耗?这是因为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
将在RandomAccessFile
尝试编写文件时打开以进行读写(rw模式)。
因此,使用Workbook.write(FileOutputStream)
可能只适合阅读或从一个文件读取并保存到另一个文件。但是直到现在使用File
来读取和写入同一个文件并不是一个好主意。对于此File
和FileInputStream
更好。