七、SXSSFWorkbook生成大excle,避免内存溢出

本文介绍了如何使用SXSSFWorkbook处理大数据量Excel文件,以避免内存溢出问题。SXSSFWorkbook通过将部分数据存储在硬盘上,以硬盘空间换取内存。文中提到了两种可能导致内存溢出的情况:数据库数据读取和文件写入,并提供了优化方案,如分页查询和设置内存中保存的行数。同时,给出了相关代码示例。
摘要由CSDN通过智能技术生成

1.SXSSFWorkbook理解:
  SXSSFWorkbook是用来生成海量excel数据文件,主要原理是借助临时存储空间生成excel,SXSSFWorkbook专门处理大数据,对于大型excel的创建且不会内存溢出的,就只有SXSSFWorkbook了。它的原理很简单,用硬盘空间换内存(就像hashmap用空间换时间一样)。 SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的excel rows在内存里供查看,在此之前的excel rows都会被写入到硬盘里(Windows电脑的话,是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。
注:HSSFWorkbook和XSSFWorkbook的Excel Sheet导出条数上限(<=2003版)是65535行、256列,(>=2007版)是1048576行,16384列,如果数据量超过了此上限,那么可以使用SXSSFWorkbook来导出。实际上上万条数据,甚至上千条数据就可以考虑使用SXSSFWorkbook了。
注意:首先需要引入依赖:注意:4.0.0版本的JDK需要1.8以上,如果JDK是1.7的,那么就使用3.9版本的依赖

2.数据过多使用SXSSFWorkbook也是会出现内存溢出的问题,主要出现的两个地方:
a.从数据库读取数据到内存时溢出。
    优化角度1:取数据时用分页的方法分批取数据,然后写入sheet中。这样就可以避免取数据时内存溢出;
    java.lang.OutOfMemoryError:GC overhead limit exceeded
b.FileOutputStream os = new FileOutputStream(path); wb.write(os);
    优化角度2:    创建Workbook时设置工作簿保存在内存中数据的条数,这样一旦这个Workbook中数据量超过1000就会写入到磁盘中,减少内存的使用量来提高速度和避免溢出。
    Workbook wb = new SXSSFWorkbook(1000);

3.通过分页查询实现海量excle数据的导出,避免发生OOM代码如下:

@RequestMapping("/exportPurchaseInfo.do")
@ResponseBody
public void exportPurchaseGoodsInfo(HttpServletRequest request, HttpServletResponse response,QueryParamDto reqDto) {
    try {
            int pageSize = 1000;//分页的大小,即每次分页查询多少条记录开关
            String[] headers = {"序号","商品编号","商品名称","品类","品牌","采购金额(元)","采购数量(件)"};
            SXSSFWorkbook workbook = ExportExcelByPageUtil.makeSXSSFWorkbook(purchseReportExportExcelByPageService,reqDto, headers, pageSize);
            ExportExcelByPageUtil.exportExcel(request, response, workbook, "商品销售报表.xlsx");
            
        } catch (Exception e) {
            logger.error("导出商品销售报表异常",e);
        }

}
View Code

ExportExcelByPageUtil.java

public static <T> SXSSFWorkbook makeSXSSFWorkbook(ReportExportExcelByPageService<T> exportExcelByPageTyService, T queryDataBo, String[] headers, int pageSize){
        int rowAccessWindowSize = 100;
        //这样表示SXSSFWorkbook只会保留100条数据在内存中,其它的数据都会写到磁盘里,这样的话占用的内存就会很少
        SXSSFWorkbook workbook = new SXSSFWorkbook(rowAccessWindowSize);
        SXSSFSheet sheet = (SXSSFSheet) workbook.createSheet("sheet1");
        Map<String,CellStyle> cellStyles=getCellStyle(workbook);
        CellStyle cs = cellStyles.get("cs");
        CellStyle cs2 = cellStyles.get("cs2");

        //设置列名
        Row row = sheet.createRow((short) 0);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(cs);
        }

        String pattern = "yyyy-MM-dd HH:mm:ss";
        String beginTime = DateUtil.formatDate(new Date(), pattern);
        int allCount = exportExcelByPageTyService.queryAllCount(queryDataBo);
        if(allCount <= 0){
            return workbook;
        }

        //处理数据量超过一个sheet页最大量时异常,支持的最大导出数据量为10000
        int maxExportCount = 10000;
   
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值