zoukankan      html  css  js  c++  java
  • POI3.8解决导出大数据量excel文件时内存溢出的问题

    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

  • 相关阅读:
    修改flex应用默认的装载界面 (转载)
    Map Tile 切图小工具 (转载)
    Virtual Earth Tile Image URI 参数解析(收集,学习VE插件必看)
    WorldWind学习系列十五:如何切割影像和DEM数据及其在WW中的应用配置
    ArcGIS Server建立缓存(切图)原理解析[图解] (转载)
    自制户外登山地图傻瓜书(转载)
    WorldWind学习系列十二:Measure插件学习
    MySQL备份
    aptitude包管理工具
    MySQL的Limit查询
  • 原文地址:https://www.cnblogs.com/feng-gamer/p/5884909.html
Copyright © 2011-2022 走看看