我需要在一个已经存在的模板(.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”写入磁盘,该怎么办?
因此对这三个产生了疑问,
什么是FlushedRows?在尝试创建新行时,它如何刷新行106403?
什么是“写入磁盘”?
使用参数“ rowAccessWindowSize”初始化“ SXSSFWorkbook”时,在我的情况下是200,什么是rowAccessWindowSize,它将做什么?
答案 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的行。