POI3.8解決導出大數據量excel文件時內存溢出的問題

POI3.8的SXSSF包是XSSF的一個擴展版本,支持流處理,在生成大數據量的電子表格且堆空間有限時使用。SXSSF經過限制內存中可訪問的記錄行數來實現其低內存利用,當達到限定值時,新一行數據的加入會引發老一行的數據刷新到硬盤。java

       好比內存中限制行數爲100,當行號到達101時,行號爲0的記錄刷新到硬盤並從內存中刪除,當行號到達102時,行號爲1的記錄刷新到硬盤,並從內存中刪除,以此類推。apache

       rowAccessWindowSize表明指定的內存中緩存記錄數,默認爲100,此值能夠經過緩存

new SXSSFWorkbook(int rowAccessWindowSize)或SXSSFSheet.setRandomAccessWindowSize(intwindowSize)來設置。dom

       SXSSF在把內存數據刷新到硬盤時,是把每一個SHEET生成一個臨時文件,這個臨時文件可能會很大,有能夠會達到G級別,若是文件的過大對你來講是一個問題,你可使用下面的方法讓SXSSF來進行壓縮,固然性能也會有必定的影響。xss

    SXSSFWorkbook wb = new SXSSFWorkbook();性能

    wb.setCompressTempFiles(true); // temp files will be gzipped測試

例子:大數據

生成三個SHEET,每一個SHEET有6000行記錄,共18萬行記錄flex

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值,用上面的例子進行耗時測試,結果以下:spa

 

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

相關文章
相關標籤/搜索