При экспорте бизнес-данных в таблицу Excel, когда объем данных в задаче экспорта велик, экспортируемый проект переполняет память.В этой статье используется Java для управления классом SXSSFWorkbook Poi для экспорта, чтобы решить проблему переполнения памяти.
1. Примите SXSSFWorkbook в Poi
При реализации экспорта в Excel всегда может произойти переполнение памяти, когда объем данных слишком велик. Переполнения памяти можно избежать, используя класс SXSSFWorkbook, предоставляемый POI.
2. Введение Poi в maven
<!-- 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的情况下
), получается, что переполнения памяти нет, и 1 000 000 строк тестовых данных можно экспортировать без изменений.Весь код 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
Когда данные достигают определенного уровня, данные будут записаны во временный файл, который не будет постоянно занимать память, поэтому о переполнении памяти не будет сообщено.