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
條資料,寫資料速度快,占用更少的記憶體,但是過程中會産生臨時檔案,需及時清理。