POI3.8的SXSSF包是XSSF的一個擴展版本,支持流處理,在生成大數據量的電子表格且堆空間有限時使用。SXSSF通過限制內存中可訪問的記錄行數來實現其低內存利用,當達到限定值時,新一行數據的加入會引起老一行的數據刷新到硬盤。
比如內存中限制行數為100,當行號到達101時,行號為0的記錄刷新到硬盤並從內存中刪除,當行號到達102時,行號為1的記錄刷新到硬盤,並從內存中刪除,以此類推。
rowAccessWindowSize代表指定的內存中緩存記錄數,默認為100,此值可以通過
new SXSSFWorkbook(int rowAccessWindowSize)或SXSSFSheet.setRandomAccessWindowSize(intwindowSize)來設置。
SXSSF在把內存數據刷新到硬盤時,是把每個SHEET生成一個臨時文件,這個臨時文件可能會很大,有可以會達到G級別,如果文件的過大對你來說是一個問題,你可以使用下面的方法讓SXSSF來進行壓縮,當然性能也會有一定的影響。
SXSSFWorkbook wb = new SXSSFWorkbook();
wb.setCompressTempFiles(true); // temp files will be gzipped
例子:
生成三個SHEET,每個SHEET有6000行記錄,共18萬行記錄
importjava.io.FileOutputStream; importorg.apache.poi.ss.usermodel.Cell; importorg.apache.poi.ss.usermodel.Row; importorg.apache.poi.ss.usermodel.Sheet; importorg.apache.poi.ss.util.CellReference; importorg.apache.poi.xssf.streaming.SXSSFSheet; importorg.apache.poi.xssf.streaming.SXSSFWorkbook; public classSXSSFWorkBookUtil { public voidtestWorkBook() { try{ longcurr_time=System.currentTimeMillis(); introwaccess=100;//內存中緩存記錄行數 /*keep 100 rowsin memory,exceeding rows will be flushed to disk*/ SXSSFWorkbook wb = newSXSSFWorkbook(rowaccess); intsheet_num=3;//生成3個SHEET for(inti=0;i<sheet_num;i++){ Sheet sh = wb.createSheet(); //每個SHEET有60000ROW for(intrownum = 0; rownum < 60000; rownum++) { Row row = sh.createRow(rownum); //每行有10個CELL for(intcellnum = 0; cellnum < 10; cellnum++) { Cell cell = row.createCell(cellnum); String address = newCellReference(cell).formatAsString(); cell.setCellValue(address); } //每當行數達到設置的值就刷新數據到硬盤,以清理內存 if(rownum%rowaccess==0){ ((SXSSFSheet)sh).flushRows(); } } } /*寫數據到文件中*/ FileOutputStream os = newFileOutputStream("d:/data/poi/biggrid.xlsx"); wb.write(os); os.close(); /*計算耗時*/ System.out.println("耗時:"+(System.currentTimeMillis()-curr_time)/1000); } catch(Exception e) { e.printStackTrace(); } } }
對於不同的rowAccessWindowSize值,用上面的例子進行耗時測試,結果如下:
rowAccessWindowSize Time(s) 5000 293 1000 69 500 43 100 20 50 18 10 16 1 15
以上測試結果是在個人筆記本電腦上進行的,配置為:
Dual-Core CPU T4400 2.2GHz 2.19GHz
Memory 1.86GB
以上測試過程只是進行了一次,並沒有多次測試求平均值,數據也只想表達當設置不同的rowAccessWindowSize值,耗時的一種趨勢。
可見一般情況下,使用默認值100即可。
參考 http://xtadg.iteye.com/blog/1703572
http://javaflex.iteye.com/blog/1264127
2016-11-23
poi讀取excel時
hssfSheet.getLastRowNum();//最后一行行標,比行數小1
hssfSheet.getRow(k).getLastCellNum();//獲取列數,比最后一列列標大1