欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POI解决导出大数据量excel文件时内存溢出的问题SXSS

程序员文章站 2022-07-13 13:17:49
...

POI3.8解决导出大数据量excel文件时内存溢出的问题
博客分类: 2012年10月
poiexcel大数据量导出内存溢出

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即可。