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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java导入excel数据出现内存溢出问题可以通过以下几种方法来解决: 1. 分批导入:将大数据分成多个小批次导入,每次只处理一部分数据,避免一次性加载全部数据导致内存溢出。可以按照行或者列进行分批导入,读取一部分数据后进行处理,然后再读取下一部分数据。 2. 内存优化:在导入数据,可以优化内存使用,减少内存消耗。例如,使用SXSSF模式代替XSSF模式,SXSSF模式可以将Excel数据写入临文件而不是全部加载到内存中,减少内存压力。 3. 限制每次读取的数据:可以通过设置读取数据的行数或者列数限制来减少内存使用。例如,使用Apache POI库的setReadWindow方法来限制每次读取的行数和列数。 4. 增加JVM内存:通过增加JVM的内存限制来避免内存溢出问题。可以通过调整-Xms和-Xmx参数来增加JVM的初始内存和最大内存限制。 5. 优化代码逻辑:检查和优化导入数据的代码逻辑,确保没有内存泄漏或者无用的数据加载。可以使用工具来进行代码分析,找出潜在的问题并进行优化。 6. 使用缓存机制:对于重复的数据,可以使用缓存机制来减少重复加载。可以将已经读取的数据缓存起来,在需要的候直接从缓存中获取,避免重复读取导致的内存占用过高。 7. 使用数据库存储:对于大数据的导入,可以考虑将数据存储在数据库中,而不是全部加载到内存中。可以使用数据库的批插入操作来提高导入效率。 综上所述,解决java导入excel数据出现内存溢出问题可以通过分批导入、内存优化、限制每次读取的数据、增加JVM内存、优化代码逻辑、使用缓存机制以及使用数据库存储等方法来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值