使用Apache poi读取excel文件时的内存问题

时间:2017-08-30 16:14:49

标签: java memory memory-leaks apache-poi

当我尝试使用apache poi库(版本3.16)读取excel文件(5.9Mb,总共37列,以及使用SUM(A1:A50)等公式的7列)时,我有内存问题。这是我的代码:

public static ArrayList<ReturnObject> readExcel(InputStream inputStreamExcelData) {

    ArrayList<ReturnObject> list = new ArrayList<ReturnObject>();

    try {
        //Here is the problem
        workbook = new XSSFWorkbook(inputStreamExcelData);
        Sheet firstSheet = workbook.getSheetAt(0);
        Iterator<Row> iterator = firstSheet.iterator();

        while (iterator.hasNext()) {
            Row nextRow = iterator.next();

            ReturnObject reg = new ReturnObject();

            Cell cell = nextRow.getCell(0);
            reg.setData1(getValueCell(cell));

            cell = nextRow.getCell(1);
            reg.setData2(getValueCell(cell));

            list.add(reg);
        }

        workbook.close();
        inputStreamExcelData.close();

    } catch (IOException e) {
        logger.error("", e);
    }
    return list;
}

getValueCell函数:

  public static String getValueCell(Cell cell) {

    String result = "";

    if (cell != null) {

        switch (cell.getCellTypeEnum()) {
        case STRING:
            result = cell.getStringCellValue();
            break;
        case NUMERIC:
            Double num = cell.getNumericCellValue();
            result = num.longValue() + "";
            if (DateUtil.isCellDateFormatted(cell)) {

                String value = sdf.format(cell.getDateCellValue());
                return value;
            }
            break;
        case FORMULA:
            CellValue cellValue = evaluator.evaluate(cell);
            result = cellValue.getStringValue();
        default:
            break;
        }
     }

     return result;
 }

主要方法

public static void main(String... args){
      InputStream is = new FileInputStream("/files/file.xlsm");
      List<ReturnObjec>  r = readExcel(is);
      System.out.ptintln(r);
}

ReturnObjec类:

 public class ReturnObject{
    private String data1;
    private String data2;
    ... setters and getters ...

} 

当我第一次跑步时,它运行正常,但我的内存使用量大幅增加(58%至74%)并留在这里。当我运行secont尝试时,内存使用量再增加一次到77%,然后,我得到内存泄漏异常。

  

线程“ajp-bio-8009-AsyncTimeout”中的异常java.lang.OutOfMemoryError:超出GC开销限制       at java.util.concurrent.ConcurrentLinkedQueue.iterator(ConcurrentLinkedQueue.java:663)       at org.apache.tomcat.util.net.JIoEndpoint $ AsyncTimeout.run(JIoEndpoint.java:157)

如何管理此内存问题?我认为 workbook.close()会释放一些内存,但它不会发生。

1 个答案:

答案 0 :(得分:0)

尝试 XSSF和SAX(事件API)。阅读应该看起来像这样:

OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );

更多信息请访问XSSF SAX APISXSSF