Maven依赖:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.10-FINAL</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.10-FINAL</version>
</dependency>
举例:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class PoiTest {
/* testGenerateXSSFWorkbook
性能分析:
1)Workbook这个对象一直在不断增大,占用了堆中的大量空间,从而导致GC
2)但是这个对象仍然在引用链上,故不会被回收掉,进而JVM会频繁地GC
3)经过多次GC后,这个对象已经进入老年代,故JVM会进行Full GC
4)JVM在进行了大量的Full GC后仍然没有更多可用的空间,最终导致堆内存溢出。
优化方案:
数据比较大时,将内存中的数据刷新到磁盘中,减少内存的使用量,进而减少GC的次数,起到以空间换时间作用,提高效率。
*/
public static void testGenerateXSSFWorkbook() {
System.out.println("开始生成Excel文件。");
Long start = System.currentTimeMillis();
XSSFWorkbook wb = new XSSFWorkbook();
// 创建并初始化sheet
Sheet sheet = wb.createSheet("测试计划");
int rowNumber = 10000 * 100; // 行数
int columnNumber = 8; // 列数
int count = 0;
for (int i = 0; i < rowNumber; i++) {
// 创建行
Row row = sheet.createRow(i);
for (int j = 0; j < columnNumber; j++) {
// 创建单元格并赋值
String cellValue = "测试内容:这是cell的内容";
row.createCell(j).setCellValue(cellValue);
}
System.out.println(count++);
}
Long end = System.currentTimeMillis();
System.out.println("XSSFWorkbook constructed. " + "Cost:" + (end - start) + " ms");
try {
wb.write(new FileOutputStream("C:/Users/jinxiaoning/Desktop/aaa/测试.xlsx"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("成功生成Excel文件。");
// 说明:在-Xmx4096m -Xms4096m 下,执行到501053行时,内存基本就被打满了,程序几乎不在向下进行了!
}
/**
* 优化
*/
public static void testGenerateSXSSFWorkbook() {
System.out.println("开始生成Excel文件。");
Long start = System.currentTimeMillis();
int memoryRowNum = 200;
// keep memoryRowNum rows in memory, exceeding rows will be flushed to disk ,memoryRowNum 默认是100
SXSSFWorkbook wb = new SXSSFWorkbook(memoryRowNum);
// whether to use gzip compression for temporary files 是否对刷新到磁盘上的临时文件进行压缩
wb.setCompressTempFiles(true);
// 创建并初始化sheet
Sheet sheet = wb.createSheet("测试计划");
int rowNumber = 10000 * 100; // 行数
int columnNumber = 8; // 列数
int count = 0;
for (int i = 0; i < rowNumber; i++) {
// 创建行
Row row = sheet.createRow(i);
for (int j = 0; j < columnNumber; j++) {
// 创建单元格并赋值
String cellValue = "测试内容:这是cell的内容";
row.createCell(j).setCellValue(cellValue);
}
System.out.println(count++);
}
Long end = System.currentTimeMillis();
System.out.println("SXSSFWorkbook constructed. " + "Cost:" + (end - start) + " ms");
try {
wb.write(new FileOutputStream("C:/Users/jinxiaoning/Desktop/aaa/测试.xlsx"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("成功生成Excel文件。");
// 补充:sheet.getRow(rownum)方法只能获取到内存中的数据(即:只能获取最近memoryRowNum行的数据),不能获取序列化到磁盘上的数据。
}
public static void main(String[] args) throws Throwable {
testGenerateXSSFWorkbook();
// testGenerateSXSSFWorkbook();
}
}
优化方法testGenerateSXSSFWorkbook()执行的结果:
生成的Excel文件:
测试.xlsx大小为19.9M
不压缩临时文件结果:
时间:SXSSFWorkbook constructed. Cost:64697 ms
临时文件:
大小:983M
位置:C:\Users\jxn\AppData\Local\Temp\poi-sxssf-sheet136052270586183201.xml
压缩临时文件的结果:
时间:SXSSFWorkbook constructed. Cost:67774 ms
临时文件:
大小:19.9M,与生成的Excel文件的大小几乎相等。
位置:C:\Users\jxn\AppData\Local\Temp\poi-sxssf-sheet-xml5730563994406788419.gz
说明:poi-sxssf-sheet-xml5730563994406788419.gz解压后得到的文件poi-sxssf-sheet-xml5730563994406788419大小为983M
针对内存中数据的行数memoryRowNum的测试结果:
1000 不压缩:SXSSFWorkbook constructed. Cost:63350 ms
10 不压缩:SXSSFWorkbook constructed. Cost:63097 ms