Apache POI Excel速度
POI基本概念
1. POI针对目前存在的两种版本的Excel有不同的实现方式.而对于相同版本的Excel又分为Dom解析和Sax解析两种.而这两种在内存使用,性能各方面均有不同.
- usermodel,它是基于DOM的文档驱动,读写都支持,基于内存的,总之就是很垃圾
- SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。
- sxssf,sxssf是xssf的一个与PI兼容的流扩展,在需要生成非常大的表格时使用,堆空间有限。SXSSF通过限制对滑动窗口中的行的访问来实现其低内存占用,而xssf允许访问文档中的所有行。它你可理解为缓存流式支持,在写文件很重要。
2.03和07版xls区别?
- a.支持文档类型不同
-
03版: 只支持xls类型的文档
-
07版: 除了支持xls类型文档,还支持xlsx类型的文档
-
- b.行数限制
-
03版: 65536行、
-
07版: 1048576行
-
大数据量处理
- 03版:HSSFWorkbook(基于usermodel)
-
优点:过程中写入缓存,不操作磁盘,最后一次性写如磁盘,速度快
-
缺点:最多只能处理65536行
-
- 07版:XSSFWorkbook(基于usermodel)
-
优点:可以写入较大的数据
-
缺点:写入数据速度非常慢,非常耗内存,也会发生内存溢出
-
- 升级版:SXSSFWorkbook(基于sxssf)
-
优点:可以写非常大的数据量,写入速度快,占用更少的内存
-
注意:过程中会产生临时文件,需清理临时文件(.dispose())
-
默认由100条记录被保存再内存中,如果超过这个数量,则最前面的数据被写入到临时文件中
-
如果想自定义内存中数据的量,可以使用new SXSSFWorkbool(数量);
-
它的原理很简单,用硬盘空间换内存(就像hash map用空间换时间一样)
-
三种方式数据处理测试
@Test
public void testCompare03(){
Long startTime=System.currentTimeMillis();
//1.创建一个工作簿
Workbook workbook=new HSSFWorkbook();
//2.创建一个工作表
Sheet sheet=workbook.createSheet("第一个工作表");
int rowNum=65536;
int cellNum=10;
for (int i = 0; i < rowNum; i++) {
//3.创建一行
Row row=sheet.createRow(i);
for (int i1 = 0; i1 < cellNum; i1++) {
//4.创建单元格
Cell cell=row.createCell(i1);
cell.setCellValue("你好呀"+i1);
}
}
System.out.println("共耗时"+(System.currentTimeMillis()-startTime)/1000+"秒");
//生成一张表 03版本使用xls结尾
try {
FileOutputStream fileOutputStream=new FileOutputStream("D:"+ File.separator+"excelTest.xls");
workbook.write(fileOutputStream);
fileOutputStream.close();
Long endTime=System.currentTimeMillis();
System.out.println("生成完毕共耗时:"+(endTime-startTime)/1000+"秒");
} catch (Exception e) {
e.printStackTrace();
}
/* 共耗时0秒
生成完毕共耗时:2秒*/
}
可以看到使用HSSFWorkbook测试的是65536
条数据,最后一次性写入磁盘,所以速度较为快速。
@Test
public void testCompare07(){
Long startTime=System.currentTimeMillis();
//1.创建一个工作簿
Workbook workbook=new XSSFWorkbook();
//2.创建一个工作表
Sheet sheet=workbook.createSheet("第一个工作表");
int rowNum=100000;
int cellNum=10;
for (int i = 0; i < rowNum; i++) {
//3.创建一行
Row row=sheet.createRow(i);
for (int i1 = 0; i1 < cellNum; i1++) {
//4.创建单元格
Cell cell=row.createCell(i1);
cell.setCellValue("你好呀"+i1);
}
}
System.out.println("共耗时"+(System.currentTimeMillis()-startTime)/1000+"秒");
//生成一张表 07版本使用xlsx结尾
try {
FileOutputStream fileOutputStream=new FileOutputStream("D:"+ File.separator+"excelTest1.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
Long endTime=System.currentTimeMillis();
System.out.println("07版生成完毕共耗时:"+(endTime-startTime)/1000+"秒");
} catch (Exception e) {
e.printStackTrace();
}
/*共耗时19秒
07版生成完毕共耗时:27秒*/
}
可以看到使用XSSFWorkbook测试的是100000
条数据,非常耗内存,超过1000000条数据也会发生内存溢出。
@Test
public void testCompare07S(){
Long startTime=System.currentTimeMillis();
//1.创建一个工作簿
Workbook workbook=new SXSSFWorkbook(100);
//2.创建一个工作表
Sheet sheet=workbook.createSheet("第一个工作表");
int rowNum=100000;
int cellNum=10;
for (int i = 0; i < rowNum; i++) {
//3.创建一行
Row row=sheet.createRow(i);
for (int i1 = 0; i1 < cellNum; i1++) {
//4.创建单元格
Cell cell=row.createCell(i1);
cell.setCellValue("你好呀"+i1);
}
}
System.out.println("共耗时"+(System.currentTimeMillis()-startTime)/1000+"秒");
//生成一张表 07升级版本使用xlsx结尾
try {
FileOutputStream fileOutputStream=new FileOutputStream("D:"+ File.separator+"excelTest1S.xlsx");
workbook.write(fileOutputStream);
fileOutputStream.close();
((SXSSFWorkbook) workbook).dispose();//清理临时文件
Long endTime=System.currentTimeMillis();
System.out.println("升级版生成完毕共耗时:"+(endTime-startTime)/1000+"秒");
} catch (Exception e) {
e.printStackTrace();
}
/* 共耗时3秒
升级版生成完毕共耗时:5秒*/
}
可以看到使用SXSSFWorkbook测试的是100000
条数据,写数据速度快,占用更少的内存,但是过程中会产生临时文件,需及时清理。