当前位置: 首页 > 知识库问答 >
问题:

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

凤凡
2023-03-14

因此,使用Apache POI的Excel中出现不可读内容错误的主题似乎很常见。然而,我感到惊讶的是,我仍然找不到我的问题的例子,特别是因为我试图做的事情似乎非常简单。这让我相信,随着我对一些java对象,特别是File和FileInputStream的理解,我的脑海中可能会浮现出一些东西。我通过大量的尝试和错误发现了如何使其工作,但我的问题是为什么一个工作,为什么另一个不工作,我很想了解根本问题。我认为这也可以帮助其他人理解。这正是我想要做的:

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

下面是不起作用的代码和起作用的代码,我想知道为什么使用File对象不起作用。在这两个示例中,我已经使用名为Voucher_1的工作表创建了TravelVouchers.xlsx文件,打开它可以正常工作。

以下代码导致travelVouchersWkBk上出现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中出现错误,即存在无法读取的内容,当我选择修复时,我可以打开它,它只有凭单1。显然是使用WorkbookFactory。使用File对象创建不起作用,而使用FileInputStream则起作用,但我想知道我对File与FileInputStream之间的关系有什么不理解,因为它与这个问题有关。

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

共有1个答案

习高格
2023-03-14

我认为使用带有WorkbookFactory的文件来读取工作簿,然后写入相同的工作簿,直到现在都不是一个好主意。apache POI文档提到:

文件与输入流

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

但是为什么使用File对象可以降低内存消耗呢?这是因为WorkbookFactory然后创建了一个随机访问文件,它不需要在内存中完全读取。要验证这一点,请阅读WorkbookFactory.java的源代码-

但据我所知,不可能访问这个随机访问文件。因此,我们无法写入它,也无法在不关闭整个工作簿的情况下关闭它。因此,在上面的示例中,将打开随机访问文件(rw模式)进行读写,而工作簿。write(FileOutputStream)尝试写入文件。

因此,使用文件可能适合于仅读取或从一个文件读取并保存到另一个文件。但是直到现在,使用文件来读写同一个文件还不是一个好主意。因此,文件输入流和文件输出流更好。

 类似资料:
  • 我需要写数据到现有的模板与格式存储在其中,但样式(字体,颜色,边框)消失。我做了什么?加载表并在其中获取工作表: 我对这件事的了解?前面我使用same而不使用null检查,在这种情况下,所有样式都将消失。现在,如果cell和row不是null(不是在java代码中重新创建的),格式保存,但是它们预先初始化时的情况是非常不同的。有时数据初始化它,有时不初始化,有时具有特定建立的样式的单元格是预先初始

  • 问题内容: 示例代码: 在代码中,我已经执行了一些无效的读取和无效的写入,但是这个小程序可以正常工作,并且不会创建。 但是一旦进入我的大库,每当我进行1个字节的无效读取或无效写入时,它总是在创建核心转储。 题: 为什么有时我会通过无效的读/写操作获得核心转储,而有时却没有获得核心转储? 问题答案: 您想要做的基本上是缓冲区溢出&在您的代码示例中,更具体地说是堆溢出。您有时只看到崩溃的原因取决于您正

  • 我注意到了ListBoxItem的这个奇怪的事情,即使你实际上没有对你创建的ListBoxItem做任何事情,如果它的内容不为空,它也会导致2个绑定错误。请注意,我没有创建任何绑定,我已经发布了重现这些错误所需的所有代码。 或者 不会导致任何错误,但 这方面的结果: 系统.Windows。数据错误:4:无法找到引用“RelativeSource FindAncestor,AncestorType=

  • 问题内容: 我有一个名为tblAccounts的表,其内容将来自excel电子表格。 我在Windows 8.1(x64)上使用MS SQL Server 2008(x64) 我尝试使用SQL Server导入/导出向导,但是没有选择现有表的选项,只有一个创建新表的选项。 我尝试使用其他方法,例如OPENROWSETS 但是给了我一个错误: 消息7308,级别16,状态1,行1 OLE DB提供程

  • 问题内容: 我想替换第二行的文件内容,请根据以下文件格式和侦听器方法来帮助您。 第二行很长,要替换为。 问题答案: 如对类似问题的公认答案中所建议: 同时以写入模式打开一个临时文件,对于每一行,读取它,必要时进行修改,然后写入该临时文件。最后,删除原始文件并重命名临时文件。 根据您的实现,类似于以下内容:

  • 问题内容: 我想使用Java程序删除文件的某些内容,如下所示。这是在相同文件中替换的写方法,还是应将其复制到另一个文件。 但是它删除了文件的所有内容。 问题答案: 我将从关闭阅读器和刷新书写器开始: