内存不足错误 - 写入Excel时的Java堆空间

时间:2013-01-10 13:56:10

标签: java excel apache-poi

我有大约100,000条记录的数据,我正在尝试使用.xlsx通过Java代码将数据写入XSSFWorkbook文件。我能够将数据库中的所有数据提取到ArrayList。通过迭代ArryList,我将数据逐个单元地写入.xlsx文件。 当它达到8000行时,java代码抛出Out of Memory Heap Space错误。

我在某处读到SXSSFWorkbookXSSFWorkbook相比会更轻,所以我尝试使用SXSSFWorkbook。但我仍面临同样的问题。

因此,我在工作簿或我的Java代码中缺少任何内容吗?

最初,当我有60,000条记录数据时,我使用了.xls文件。相同的java代码能够使用.xls生成HSSFWorkbook文件。

增加Java堆空间根本不是一个选项,因为将来我的数据会大大增加。

非常感谢任何帮助。

一小段代码,就是我将数据写入Excel的方式。

int rowNum = sheet.getLastRowNum();

Row lastRow = null ;

Cell cell = null;

ReportingHelperVo reportingHelperVo = null; 

for (ReportingVo reportingVo : reportingVos) {

rowNum++;

lastRow = sheet.createRow(rowNum);

reportingHelperVo = reportingVo.reportingHelperVo;

cell = lastRow.createCell(0);

cell.setCellValue(reportingHelperVo.getLocation());

cell.setCellStyle(style);

cell = lastRow.createCell(1);

cell.setCellValue(reportingHelperVo.getCity());

cell.setCellStyle(style);

cell = lastRow.createCell(2);

cell.setCellValue(reportingHelperVo.getCountry());

cell.setCellStyle(style);

}

9 个答案:

答案 0 :(得分:5)

XSSFWorkbook - 为所有Excel文档创建一个对象表示(应该像DOM一样工作)。

SXSSFWorkbook - 应该需要恒定的记忆。 JMV何时抛出OOM?你使用了什么类型的ResultSet?尝试使用FORWARD_ONLY来限制从DB检索到的JDBC驱动程序的缓存数据。

BTW最好修复OutOfMemoryError是分析堆转储。 使用-XX:+ HeapDumpOnOutOfMemoryError参数和MAT来了解应用程序的工作方式。

答案 1 :(得分:2)

  

我正逐个单元地将数据写入.xlsx文件。随着它到达   8000行,java代码抛出内存堆空间错误。

重复使用现有的java对象,而不是每次迭代都创建new个。

和/或使用csv文件而不是excel。

答案 2 :(得分:2)

SXSSFWorkbook不像轻量级,但这有一个优点。

如果您声明为

SXSSFWorkbook workbook= new SXSSFWorkbook(200);

然后,对于写在工作簿上的每200行,内存将被刷新到磁盘空间,因此堆空间不会有任何负担。

答案 3 :(得分:1)

Workbook workBook = new SXSSFWorkbook();

您可以导出超过1万(100000)条记录。

答案 4 :(得分:0)

页面来自数据库,而不是一次性读取它们。

答案 5 :(得分:0)

我很久以前就有类似的问题试图从R写入excel文件(但使用XLConnection)。 最后,我通过使用write.csv解决,然后用Excel打开它并使用botton“Text to column”。 它增长迅速可靠。

答案 6 :(得分:0)

当我的excel达到3000行时,我遇到了同样的问题。在我的情况下,POI Excel生成的主要内存相关问题发生在样式表中。以下是我从代码中删除的内容。

  1. 尝试在行级别中使用样式表设置。
  2. 如果您需要为每个单元格设置样式表,请避免为每个单元格设置边框。

答案 7 :(得分:0)

您使用最新的Apache POI JAR //并使用SXSSF进行流式传输或下载

 SXSSFWorkbook workbook = new SXSSFWorkbook(100); 
            workbook.setCompressTempFiles(true);
            Sheet sh = workbook.createSheet();
            ((SXSSFSheet) sh).setRandomAccessWindowSize(100);

//写你的逻辑

   response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment; 
       filename="+filename+".xlsx");
            workbook.write(response.getOutputStream());
            workbook.close();
            workbook.dispose();

答案 8 :(得分:0)

我在将XSSFWorkbook写入文件时遇到内存不足的问题。
上面的建议很有帮助。
参见http://poi.apache.org/components/spreadsheet/how-to.html#xssf_sax_api

  1. 更改XSSFWorkbook wb = new XSSFWorkbook();
        到SXSSFWorkbook wb =新的SXSSFWorkbook(-1);
        SXSSFSheet sh = ...到SXSSFSheet sh = ...
        XSSFRow至SXSSFRow
        XSSFCell到SXSSFCell

  2. 在for循环中使用
  3. USE sh.flushRows(100);每第100行

  4. wb.write(out)之后的
  5. ;
    添加wb.dispose();