java写excel内存溢出怎么解决?Java解决excel内存溢出技巧

有时候我们需要将excel导出以及写入,而进行这两项操作是Java开发的必备技能,可是我们在写excel的时候,肯定会遇到内存溢出的问题,那java写excel内存溢出怎么解决?下面来我们就来给大家讲解一下。

将业务数据导出到Excel表中,导出任务数据量较大时,导出的项目就会内存溢出,本文通过Java操作Poi的SXSSFWorkbook类进行导出,解决内存溢出问题。

1.采用Poi中的SXSSFWorkbook

在实现excel导出时,在数据量过大的情况下,总是容易发生内存溢出的情况。可以使用POI提供的 SXSSFWorkbook 类来避免内存溢出。

java写excel内存溢出怎么解决?Java解决excel内存溢出技巧.png

2.maven中引入Poi

<!-- poi start -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency> <
dependency >
    <groupId>org.apache.poi</groupId> <
    artifactId > poi - ooxml < /artifactId> <
    version > 4.1 .2 < /version> <
    /dependency> <
    dependency >
    <groupId>org.apache.poi</groupId> <
    artifactId > poi - ooxml - schemas < /artifactId> <
    version > 4.1 .2 < /version> <
    /dependency> <
    !--poi end-- >

3.测试过程

先使用普通的写法测试(XSSFWorkbook),编写writeNormalExcelTest测试方法,写入的行数太多时,会报内存溢出(在设置-server -Xmx64m -Xms64m -Xmn32m的情况下)。

接着编写SXSSFWorkbook操作excel的测试,测试方法writeHugeExcelTest(同样在设置-server -Xmx64m -Xms64m -Xmn32m的情况下),结果证明无内存溢出,能完好的导出1000000行测试数据,整个Java类代码如下:

4.单元测试Java代码

package cn.gzsendi.exceltest;
import java.io.FileOutputStream;
import java.io.IOException;
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.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
public class HugeExcelExportTest
{
    private int totalRowNumber = 1000000; //写入的excel数据行数
    private int totalCellNumber = 40; //excel每行共40列
    //普通的写入excel的方法,会消耗内存,写入的行数太大时,会报内存溢出
    @Test
    public void writeNormalExcelTest()
    {
        Workbook wb = null;
        FileOutputStream out = null;
        try
        {
            long startTime = System.currentTimeMillis();
            wb = new XSSFWorkbook();
            Sheet sheet = wb.createSheet("Sheet 1");
            //定义Row和Cell变量, Rows从0开始.
            Row row;
            Cell cell;
            for (int rowNumber = 0; rowNumber < totalRowNumber; rowNumber++)
            {
                row = sheet.createRow(rowNumber);
                for (int cellNumber = 0; cellNumber < totalCellNumber; cellNumber++)
                {
                    cell = row.createCell(cellNumber);
                    cell.setCellValue(Math.random()); //写入一个随机数
                }
                //打印测试,
                if (rowNumber % 10000 == 0)
                {
                    System.out.println(rowNumber);
                }
            }
            //Write excel to a file
            out = new FileOutputStream("d:\\temp\\normalExcel_" + totalRowNumber + ".xlsx");
            wb.write(out);
            long endTime = System.currentTimeMillis();
            System.out.println("process " + totalRowNumber + " spent time:" + (endTime - startTime) + " ms.");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (out != null) out.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            try
            {
                if (wb != null) wb.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    //结合临时文件压缩等写入excel,默认超过100行就写到临时文件,不会报内存溢出
    @Test
    public void writeHugeExcelTest()
    {
        SXSSFWorkbook wb = null;
        FileOutputStream out = null;
        try
        {
            long startTime = System.currentTimeMillis();
            wb = new SXSSFWorkbook(); //默认100行,超100行将写入临时文件
            wb.setCompressTempFiles(false); //是否压缩临时文件,否则写入速度更快,但更占磁盘,但程序最后是会将临时文件删掉的
            Sheet sheet = wb.createSheet("Sheet 1");
            //定义Row和Cell变量, Rows从0开始.
            Row row;
            Cell cell;
            for (int rowNumber = 0; rowNumber < totalRowNumber; rowNumber++)
            {
                row = sheet.createRow(rowNumber);
                for (int cellNumber = 0; cellNumber < totalCellNumber; cellNumber++)
                {
                    cell = row.createCell(cellNumber);
                    cell.setCellValue(Math.random()); //写入一个随机数
                }
                //打印测试,
                if (rowNumber % 10000 == 0)
                {
                    System.out.println(rowNumber);
                }
            }
            //Write excel to a file
            out = new FileOutputStream("d:\\temp\\hugeExcel_" + totalRowNumber + ".xlsx");
            wb.write(out);
            long endTime = System.currentTimeMillis();
            System.out.println("process " + totalRowNumber + " spent time:" + (endTime - startTime) + " ms.");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            if (wb != null)
            {
                wb.dispose(); // 删除临时文件,很重要,否则磁盘可能会被写满
            }
            try
            {
                if (out != null) out.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            try
            {
                if (wb != null) wb.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}
}

5.结论

导出excel数据量大时,采用SXSSFWorkbook进行操作,数据达到一定数据将写数据到临时文件,不会一直占用内存,因此不会报内存溢出。

总之遇到内存溢出的情况开发人员也不要紧张,我们可以通过SXSSFWorkbook类进行导出,解决内存溢出问题。最后大家如果想要了解更多java实例知识,敬请关注奇Q工具网。

推荐阅读:

qt中显示json数据的控件怎么使用?qt如何打包程序?

JAVA写Excel找不到路径怎么办?JAVA写入Excel实例

java工程师必备技能有哪些?java工程师工资为什么高?