前⾔
将业务数据导出到Excel表中,导出任务数据量较⼤时,导出的项⽬就会内存溢出,本⽂通过Java操作Poi的SXSSFWorkbook 类进⾏导出,解决内存溢出问题。
1.采⽤Poi中的SXSSFWorkbook
在实现excel导出时,在数据量过⼤的情况下,总是容易发⽣内存溢出的情况。可以使⽤POI提供的 SXSSFWorkbook 类来避免内存溢出。
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代码
ltest;
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 = ateRow(rowNumber);
for (int cellNumber = 0; cellNumber < totalCellNumber; cellNumber++) {
大文件发送cell = ateCell(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 = ateRow(rowNumber);
for (int cellNumber = 0; cellNumber < totalCellNumber; cellNumber++) {
cell = ateCell(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进⾏操作,数据达到⼀定数据将写数据到临时⽂件,不会⼀直占⽤内存,因此不会报内存溢出
到此这篇关于Java通过导出超⼤Excel⽂件解决内存溢出问题的⽂章就介绍到这了,更多相关Java导出超⼤Excel⽂件内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
发布评论