java向excel 写入海量数据内存溢出问题 解决

2022-07-28,,,,

由于项目中有导出海量数据的需求,在谷歌和百度也没有找到好的解决办法,经过仔细研究发现poi-3.8版本以上提供新的模式可以满足这个需求,写在这里希望能对有同样需求的同行们有所帮助。

以下是测试代码:

import java.io.FileOutputStream;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * @description:TestA
 * @author     :liuf 
 * @since      :2020/11/11 9:57
 */
public class TestA {

    /*** @param args*/
    public static void main(String[] args) {
        if (args[0].equals("hssf")) {
            hssfTest();
        }
        if (args[0].equals("sxssf")) {
            sxssfTest();
        }

    }

    public static void sxssfTest() {

        Workbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk
        Sheet sh = wb.createSheet();
        int rownum = 0;
        try {
            while (true) {
                Row row = sh.createRow(rownum);
                for (int cellnum = 0; cellnum < 10; cellnum++) {
                    Cell cell = row.createCell(cellnum);
                    String address = new CellReference(cell).formatAsString();
                    cell.setCellValue(address);
                }
                System.out.println(rownum);
                rownum++;
                if (rownum >= 1000000) break;
            }

            FileOutputStream out = new FileOutputStream("c:/sxssf.xlsx");
            wb.write(out);
            out.close();
        } catch (Exception e) {
            System.out.println(ExceptionUtils.getFullStackTrace(e));
        }
    }

    public static void hssfTest() {
        XSSFWorkbook wb = new XSSFWorkbook();
        Sheet sh = wb.createSheet();
        int rownum = 0;
        try {
            while (true) {
                Row row = sh.createRow(rownum);
                for (int cellnum = 0; cellnum < 10; cellnum++) {
                    Cell cell = row.createCell(cellnum);
                    String address = new CellReference(cell).formatAsString();
                    cell.setCellValue(address);
                }
                System.out.println(rownum);
                rownum++;
                if (rownum >= 1000000) break;
            }

            FileOutputStream out = new FileOutputStream("c:/hssf.xlsx");
            wb.write(out);
            out.close();
        } catch (Exception e) {
            System.out.println(ExceptionUtils.getFullStackTrace(e));
        }
    }
}

将工程打包成jar到C:,然后用命令行java -jar -Xms128m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=512M test.jar hssf 执行,在命令行窗口输出到45000之后,输出明显减慢,

很快输出如下异常:

5028850289502905029150292 Exception in thread “main”
        java.lang.reflect.InvocationTargetException 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)Caused by:java.lang.OutOfMemoryError:Java heap space

继续用命令行java -jar -Xms128m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=512M test.jar sxssf执行,

命令行窗口输出速度一直保持不变,直到循环完了,并最终生成四十多M的excel—sxssf.xlsx

本文地址:https://blog.csdn.net/weixin_44259233/article/details/109613425

《java向excel 写入海量数据内存溢出问题 解决.doc》

下载本文的Word格式文档,以方便收藏与打印。