关于SXSSFWorkbook的FlushedRows,写到磁盘和rowAccessWindowSize

时间:2019-07-06 08:34:16

标签: java apache-poi

我需要在一个已经存在的模板(.xlsx)上的Excel(.xlsx)文件中写入数百万条记录。最初,我使用的是XSSFWorkbook,这显然导致我遇到OOM问题。

然后,我已更改为SXSSFWorkbook以避免出现以下OOM问题,

FileInputStream fis = new FileInputStream(file);
OPCPackage pkg = OPCPackage.open(fis);
XSSFWorkbook mainBook = new XSSFWorkbook(pkg);
SXSSFWorkbook wb = new SXSSFWorkbook(mainBook,200);
Sheet sh = wb.getSheet("Sheet1");
Row row0 = sh.createRow(0);

在SXSSFWorkbook中,我们无法修改现有模板,因此我将模板保留为空以写入具有列标题的数据。

但是在row0 = sh.createRow(0);上,它会抛出类似“ java.lang.IllegalArgumentException:尝试在已经写入磁盘的row[0]范围内写入[0,106403]”之类的错误

我完全不确定,如何将“ 106403”写入磁盘,该怎么办?

因此对这三个产生了疑问,

  1. 什么是FlushedRows?在尝试创建新行时,它如何刷新行106403?

  2. 什么是“写入磁盘”?

  3. 使用参数“ rowAccessWindowSize”初始化“ SXSSFWorkbook”时,在我的情况下是200,什么是rowAccessWindowSize,它将做什么?

1 个答案:

答案 0 :(得分:1)

SXSSFWorkbook仅用于写作。当使用模板XSSFWorkbook时,则从该SXSSFWorkbook创建XSSFWorkbook时,将为该XSSFWorkbook中的每个工作表创建一个临时文件,并写入这些工作表中的所有现有行到那些临时文件中。以后,只有新行可以流式传输到这些临时文件中。

rowAccessWindowSize设置在内存中刷新到临时文件之前保留的行数。已经写入临时工作表文件的所有行以后将无法再访问,因为它们不在内存中,而仅在临时文件中。这就是SXSSF内存使用率低的原因。

错误消息java.lang.IllegalArgumentException: Attempting to write a row[0] in the range [0,106403] that is already written to disk.告诉您索引0到106403(行1到106404)的行已被写入磁盘。这表明模板Sheet1不为空。至少在行106404中必须是数据。这就是为什么在Sheet1时将行1至106404写入SXSSFWorkbook wb = new SXSSFWorkbook(mainBook,200);的临时文件的原因。之后,只能在SXSSFSheet上新建大于行号106405的行。