解决POI的XSSFWorkbook导入大excel的内存消耗过大问题

方式1:使用SXSSFWorkbook ,经过测试,这个情况无效,因为本质上SXSSFWorkbook 也是通过XSSFWorkbook来的,他可以解决写出excel的场景,但是解决不了我们这种用户上传且读取excel中的内容的场景

参考:
记一次解决poi XSSFWorkbook导出excel内存溢出换成SXSSFWorkbook还是内存溢出的问题
https://blog.csdn.net/weixin_38008837/article/details/120703835

SXSSFWorkbook workBook1 = new SXSSFWorkbook();
SXSSFSheet sheet1 = workBook1.createSheet("sheetName");
//具体要写入的业务逻辑等
//创建行 设置行样式等
...
//写入数据 设置单元格样式等
...
//不写此句,没有写入磁盘依然占用内存 之前就是没有写这句,生成的临时文件都是0kb,加上即解决了问题
sheet1.flushRows();

//正确的获取需要使用getRow的sheet的方法
Sheet sheet = workBook.getXSSFWorkbook().getSheetAt(i);

        XSSFWorkbook XSSFWorkbook =  new XSSFWorkbook(fileInputStream);
        System.gc();
        SXSSFWorkbook SXSSFWorkbook = new SXSSFWorkbook(XSSFWorkbook);

方式2:使用xlsx-streamer的方式,分段读取.
参考:https://www.cnblogs.com/longronglang/p/13942394.html

1
测试步骤
1.导入依赖

    <dependency>
      <groupId>com.monitorjbl</groupId>
      <artifactId>xlsx-streamer</artifactId>
      <version>2.0.0</version>
    </dependency>

2.设置jvm参数:-Xmx100m -Xms100M

package com.hgh;

import com.monitorjbl.xlsx.StreamingReader;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.FileInputStream;
import java.io.IOException;

/**
 * -Xmx100m -Xms100M
 *
 */
public class POIDemo3 {
    public static void main(String[] args) throws IOException {
        long maxUserMemory = 0;
        FileInputStream in = new FileInputStream("F://测试excel-50000.xlsx");
        long heapSize = Runtime.getRuntime().totalMemory();
        long heapMaxSize = Runtime.getRuntime().maxMemory();
        long heapFreeSize = Runtime.getRuntime().freeMemory();
        long memoryUse = heapSize - heapFreeSize;
        if (memoryUse >maxUserMemory){
            maxUserMemory = memoryUse;
        }
        System.out.println("heapsize"+formatSizeUtil.formatSize(heapSize));
        System.out.println("heapmaxsize"+formatSizeUtil.formatSize(heapMaxSize));
        System.out.println("heapFreesize"+formatSizeUtil.formatSize(heapFreeSize));
        System.out.println("使用内存"+formatSizeUtil.formatSize(memoryUse));
        Workbook wk = StreamingReader.builder()
                .rowCacheSize(100)  //缓存到内存中的行数,默认是10
                .bufferSize(8192)  //读取资源时,缓存到内存的字节大小,默认是1024
                .open(in);  //打开资源,必须,可以是InputStream或者是File,注意:只能打开XLSX格式的文件
        heapSize = Runtime.getRuntime().totalMemory();
        heapMaxSize = Runtime.getRuntime().maxMemory();
        heapFreeSize = Runtime.getRuntime().freeMemory();
        memoryUse = heapSize - heapFreeSize;
        if (memoryUse >maxUserMemory){
            maxUserMemory = memoryUse;
        }
        System.out.println("heapsize"+formatSizeUtil.formatSize(heapSize));
        System.out.println("heapmaxsize"+formatSizeUtil.formatSize(heapMaxSize));
        System.out.println("heapFreesize"+formatSizeUtil.formatSize(heapFreeSize));
        System.out.println("使用内存"+formatSizeUtil.formatSize(memoryUse));
        Sheet sheet = wk.getSheetAt(0);
        //遍历所有的行
        for (Row row : sheet) {
           // System.out.println("开始遍历第" + row.getRowNum() + "行数据:");
            //遍历所有的列
            for (Cell cell : row) {
                //System.out.print(cell.getStringCellValue() + " ");
            }
            heapSize = Runtime.getRuntime().totalMemory();
            heapMaxSize = Runtime.getRuntime().maxMemory();
            heapFreeSize = Runtime.getRuntime().freeMemory();
            memoryUse = heapSize - heapFreeSize;
            if (memoryUse >maxUserMemory){
                maxUserMemory = memoryUse;
            }
        }
        heapSize = Runtime.getRuntime().totalMemory();
        heapMaxSize = Runtime.getRuntime().maxMemory();
        heapFreeSize = Runtime.getRuntime().freeMemory();
        if (memoryUse >maxUserMemory){
            maxUserMemory = memoryUse;
        }
        System.out.println("heapsize"+formatSizeUtil.formatSize(heapSize));
        System.out.println("heapmaxsize"+formatSizeUtil.formatSize(heapMaxSize));
        System.out.println("heapFreesize"+formatSizeUtil.formatSize(heapFreeSize));
        System.out.println("使用内存"+formatSizeUtil.formatSize(heapSize - heapFreeSize));
        System.out.println("最大使用内存=" + formatSizeUtil.formatSize(maxUserMemory));
    }
}

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值