Java通过导出超大Excel文件解决内存溢出问题

网友投稿 729 2022-09-25


Java通过导出超大Excel文件解决内存溢出问题

前言

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

1.采用Poi中的SXSSFWorkbook

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

2.maven中引入Poi

org.apache.poi

poi

4.1.2

org.apache.poi

poi-ooxml

4.1.2

org.apache.poi

poi-ooxml-schemas

4.1.2

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 starthttp://Time = 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);

}

}

http://

//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进行操作,数据达到一定数据将写数据到临时文件,不会一直占用内存,因此不会报内存溢出


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:关于各个协议(关于各个协议的说法)
下一篇:STP/RSTP/PVST/MSTP/MSTI/CIST的概念以及Cost of path的计算(stp rstp pvst mstp的区别)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~