Java 使用Poi SXSSFWorkbook向Excel添加注释时使用的内存过多

Java 使用Poi SXSSFWorkbook向Excel添加注释时使用的内存过多,java,apache-poi,Java,Apache Poi,我的应用程序创建了一个电子表格,它可能相当大(多达500000行,每行分布在六张纸上,每行大约有20列) 我使用ApachePOI,并使用SXSSFWorkBook将数据写入临时文件,这样使用的内存和最终电子表格的大小不成正比,而且效果很好 但电子表格表示元数据已更改,当元数据已更改时,我希望在单元格中添加一条注释,显示旧值。我在小型电子表格中使用了这一功能,但在尝试处理大型文件时,它总是会因堆内存错误而失败 我不确定问题是由于Poi在内存中存储所有注释的限制,还是我做得不对。工作表是我自己的包

我的应用程序创建了一个电子表格,它可能相当大(多达500000行,每行分布在六张纸上,每行大约有20列)

我使用ApachePOI,并使用SXSSFWorkBook将数据写入临时文件,这样使用的内存和最终电子表格的大小不成正比,而且效果很好

但电子表格表示元数据已更改,当元数据已更改时,我希望在单元格中添加一条注释,显示旧值。我在小型电子表格中使用了这一功能,但在尝试处理大型文件时,它总是会因堆内存错误而失败

我不确定问题是由于Poi在内存中存储所有注释的限制,还是我做得不对。工作表是我自己的包装类,每个工作表我只创建一个DrawingPatrich类,但看起来我必须为我需要的每个注释创建一个锚

private void addCellComment(Row r, Cell c, Worksheet sheet, String value)
{
    String formattedValue    =  value.replace('\u0000', '\n');
    int    rowCount         =  value.split("\\\\u000").length;
    ClientAnchor anchor = factory.createClientAnchor();
    anchor.setCol1(c.getColumnIndex());
    anchor.setCol2(c.getColumnIndex()+2);
    anchor.setRow1(r.getRowNum());
    anchor.setRow2(r.getRowNum()+rowCount);

    Drawing drawing = sheet.getDrawing();
    Comment comment = drawing.createCellComment(anchor);
    RichTextString str = factory.createRichTextString(formattedValue);
    comment.setString(str);
    c.setCellComment(comment);
} 
嗯,从(我的):

请注意,根据您使用的功能,仍有一些东西可能会消耗大量内存,例如合并区域、超链接、注释、。。。仍然只存储在内存中,因此如果广泛使用,可能需要大量内存


因此,我想这是Apache POI的一个局限性,您必须解决这个问题。

我不确定我们如何帮助解决这个问题。在这种情况下,您可能必须求助于一个非常好的分析器,并对应用程序进行评测,以准确了解内存消耗的位置、方式和原因。需要多少内存?您的java内存设置是什么?您使用哪种java?你的工作站有多少内存?我想找一个具有Poi专业知识而不是内存分析专业知识的人。我分配1GB的内存,如果我删除创建注释部分,我可以创建一个20000行的电子表格,内存永远不会达到300mb,但是添加注释回来,它总是在堆内存上失败。我在Windows 10上使用jre1.8.0_111请你添加更多代码我想知道如何初始化SXSSFWorkbook窗口大小是多少?您是否已关闭自动刷新并使用手动控制如何将行刷新到磁盘?@SauliusNext i just do workbook=new SXSSFWorkbook(1000)-我尚未关闭刷新,如果我不添加commentcells,则它可以正常工作,使用的内存比我仅使用HSSFWorkbook时少得多。问题具体到commentcells,好的,这已经证实了这个问题,我已经提出了一个错误,怀疑这是真的。我没有一个解决办法,我看不到解决办法。就我个人而言,我会放弃将这些信息作为注释保存:在.xlsx格式中,注释存储在“带外”,因此POI需要将其保存在内存中,直到每张工作表完成。因为XLSX基本上是一串拉链XML文件,您也可以考虑生成没有注释的工作簿,然后添加解压缩的第二遍,修改XML以添加注释和重新拉链。有关这种方法的更多信息,请点击以下链接:好主意(至少在原则上可能需要一些工作)没有意识到它是xml,考虑到这一点,是否也可以按照@Christophembiminger分阶段保存并重新打开文件并附加到文件中,而无需使用poi读取所有数据,因为这很简单,您所说的“带外”是什么意思@PaulTaylor在这种情况下,如果您检查.xlsx,您将看到注释没有写入sheetXXX.xml文件,但要将其转换到另一个文件commentXXX.xml。当前POI实现无法将注释“流”到该文件中,而是保留它们,并在工作表完成时一次性写入整个commentXXX.xml文件。