我想从Excel文件读取多张大于10 mb的数据

时间:2019-06-05 22:17:08

标签: java android apache apache-poi out-of-memory

我的代码在较小的excel文件中可以正常工作,但不适用于较大的excel文件,它会显示错误OutOfMemory。

public void onReadClick (View view) {
    printlnToUser("reading XLSX file from resources");
    InputStream stream = getResources().openRawResource(R.raw.test3);
    try {
        XSSFWorkbook workbook = new XSSFWorkbook(stream);
        XSSFSheet sheet = workbook.getSheetAt(0);
        int rowsCount = sheet.getPhysicalNumberOfRows();
        FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
        for (int r = 0; r<10; r++) {
            Row row = sheet.getRow(r);
            int cellsCount = row.getPhysicalNumberOfCells();
            for (int c = 0; c<cellsCount; c++) {
                String value = getCellAsString(row, c, formulaEvaluator);
                String cellInfo = "r:"+r+"; c:"+c+"; v:"+value;
                printlnToUser(cellInfo);
            }
        }
    } catch (Exception e) {
        /* proper exception handling to be here */
        printlnToUser(e.toString());
    }
}
  

它导致以下运行时错误。请尽快提供帮助。

您的帖子似乎主要是代码;请添加更多详细信息。这很烦人。

2019-06-06 03:30:43.535 5224-5224/pro.kondratev.xlsxpoiexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: pro.kondratev.xlsxpoiexample, PID: 5224
java.lang.IllegalStateException: Could not execute method for android:onClick
    at android.view.View$DeclaredOnClickListener.onClick(View.java:4707)
    at android.view.View.performClick(View.java:5619)
    at android.view.View$PerformClick.run(View.java:22298)
    at android.os.Handler.handleCallback(Handler.java:754)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:165)
    at android.app.ActivityThread.main(ActivityThread.java:6375)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at android.view.View$DeclaredOnClickListener.onClick(View.java:4702)
    at android.view.View.performClick(View.java:5619) 
    at android.view.View$PerformClick.run(View.java:22298) 
    at android.os.Handler.handleCallback(Handler.java:754) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:165) 
    at android.app.ActivityThread.main(ActivityThread.java:6375) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) 
 Caused by:java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available

2 个答案:

答案 0 :(得分:0)

由于POI会为内存中的整个Excel文件读取,解析并创建整个数据结构,因此会出现内存不足错误。这会占用大量内存。我看到您的程序从单个工作表中读取。这告诉我您可以将该工作表导出到.csv(逗号分隔值)文件。这样就很容易读取数据。

我对您的业务流程了解不多,无法确定可以导出到.csv的位置,或者在您的流程中是否有可能。 POI因使用大量内存而臭名昭著。

另一种解决方案是直接从Excel文件中读取。 .xlsx文件实际上是一个zip。您可以打开它并从那里读取数据。您可能需要查看SpreadsheetML文档来了解.xslx zip文件的格式,或者使用Open XML SDK,就像POI会使用内存,但可能不会使用太多。

答案 1 :(得分:0)

给SXSSFWorkbook一枪。尝试使用非常高效和高性能的流式SXSSFWorkbook类,而不是XSSFWorkbook(将整个Excel工作簿保留在内存中),如下所示:

SXSSFWorkbook workbook = new SXSSFWorkbook(100);

其中100是将保留在内存中并实时处理的默认行数,其他已处理的行将被刷新。