java.lang.OutOfMemoryError:加载xlsx文件时超出了GC开销限制

时间:2015-08-07 09:13:15

标签: java garbage-collection out-of-memory apache-poi xssf

我理解错误意味着什么,我的程序消耗了太多内存,而且很长一段时间内它都没有恢复。

当内存问题发生时,我的程序只读取6,2Mb xlsx文件。

当我尝试监视程序时,内存消耗很快达到1,2Gb然后崩溃。读取6,2Mb文件时如何达到1,2Gb?

有没有办法以块的形式打开文件?这样它就不必加载到内存中了?还是其他任何解决方案?

正是这部分导致了它。但既然它是一个图书馆,难道不应该以某种方式处理它吗?它只有20万行,只有3列。对于未来,我需要它与约。 1百万条记录和更多列...

CODE:

  Workbook myWorkBook;
        Sheet mySheet;
        if (filePath.contains(".xlsx")) {
            // Finds the workbook instance for XLSX file
             myWorkBook = new XSSFWorkbook(fis);
            // Return first sheet from the XLSX workbook
             mySheet = myWorkBook.getSheetAt(0);
             myWorkBook.close(); // Should I close myWorkBook before I get data from it?
        } 

1 个答案:

答案 0 :(得分:2)

如果您希望使用大型XLSX文件,则需要使用流式XSSFReader类。由于数据是XML,因此您可以使用StAX有效地处理内容。

这是(单向)如何从xlsx获取Inputstream

OPCPackage opc = OPCPackage.open(file);
XSSFReader xssfReader = new XSSFReader(opc);
SharedStringsTable sst = xssfReader.getSharedStringsTable();
XSSFReader.SheetIterator itr = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
while(itr.hasNext()) {
    InputStream sheetStream = itr.next();
    if(itr.getSheetName().equals(sheetName)) {  // Or you can keep track of sheet numbers
        in = sheetStream;
        return;
    } else {
        sheetStream.close();
    }
}

元素是<row><c>(对于单元格)。您可以创建一个小的xlsx文件,解压缩并检查内部的XML以获取更多信息。

编辑: 使用SAX处理数据有一些examples,但使用StAX更好,效率更高。