大数据量(例如几十万或者几百万的量)怎么导入到excel中

本文介绍了解决大量数据写入Excel时内存溢出的问题,通过使用Apache POI库中的SXXFWorkbook类,实现了将超过指定行数的数据刷新到磁盘,有效避免了内存不足的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现有的方案是:

 1. 数据量达到N行(例如:100行的时候)就往磁盘中写数据(就是将结果先写到磁盘的导入文件中,最后直接导出)

     思考:前端直接导出这么大的文件,能导出吗?

实现方案:POI 解决写入excel内存溢出

POI写入excel表

下面是结构图

大批量数据读取写入的问题 

在项目中遇到二十万行数据要写入到excel中时会内存溢出,一般方法是调大tomcat的内存,但是调到2048M还是会内存溢出报错

poi官网给了一种大批量数据写入的方法

使用SXXFWorkbook 类进行大批量写入操作解决了这个问题
import junit.framework.Assert;
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 org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 
    public static void main(String[] args) throws Throwable {
        SXSSFWorkbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk
        Sheet sh = wb.createSheet();
        for(int rownum = 0; rownum < 1000; rownum++){
            Row row = sh.createRow(rownum);
            for(int cellnum = 0; cellnum < 10; cellnum++){
                Cell cell = row.createCell(cellnum);
                String address = new CellReference(cell).formatAsString();
                cell.setCellValue(address);
            }
 
        }
 
        // Rows with rownum < 900 are flushed and not accessible
        for(int rownum = 0; rownum < 900; rownum++){
          Assert.assertNull(sh.getRow(rownum));
        }
 
        // ther last 100 rows are still in memory
        for(int rownum = 900; rownum < 1000; rownum++){
            Assert.assertNotNull(sh.getRow(rownum));
        }
        
        FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");
        wb.write(out);
        out.close();
 
        // dispose of temporary files backing this workbook on disk
        wb.dispose();
    }

通过设置SXXFWorkbook的构造参数,可以设置每次在内存中保持的行数,当达到这个值的时候,那么会把这些数据flush到磁盘上,这样就不会出现内存不够的情况

参考地址: http://poi.apache.org/spreadsheet/how-to.html#sxssf

转载于:https://blog.youkuaiyun.com/daiyutage/article/details/53010491

类似的方案参考:https://blog.youkuaiyun.com/weixin_39468277/article/details/79863065

 

 

<think>好的,我现在需要帮用户解决如何使用EasyExcel生成包含几十万数据的大XLSX文件的问题。用户之前可能已经了解过EasyExcel的优势,比如内存优化,但现在需要具体的实现步骤和最佳实践。首先,我得回顾一下用户提供的引用内容,确保回答符合他们的需求。 根据引用[1]和[3],EasyExcel在处理大数据通过重写POI的解析方式,显著降低了内存使用,适合导出百万级数据。用户提到几十万,虽然不算极端,但仍需注意内存管理。引用[2]提到压缩导出的Stream closed异常,但用户的问题主要是生成单个文件,这部分可能暂不需要,但可以留作后续扩展。引用[4]和[5]分别涉及模板生成和解析,但用户现在关注的是导出,所以重点在导出流程。 接下来,我需要整理最佳实践的步骤。首先,分页查询数据是关键,避免一次性加载所有数据到内存,这符合引用[3]中的分页处理建议。然后,使用EasyExcel的WriteSheet和异步写入功能,这能进一步减少内存占用。另外,临文件的使用也很重要,因为直接写入流可能在网络中断失败,而临文件可以确保数据完整性。 在代码示例部分,需要展示如何分页查询,配置ExcelWriter,以及逐页写入数据。同,要提到模板导出和样式优化,比如禁用默认样式和设置自动列宽,这些都能提升性能和用户体验。最后,异常处理和资源清理也是必要步骤,防止资源泄漏。 可能还需要考虑用户的其他潜在问题,比如如何处理特殊数据类型,或者如何优化查询速度。不过根据当前问题,重点应放在导出流程和内存管理上。需要确保代码示例正确,并解释每一步的作用,让用户清楚最佳实践的原因。另外,引用相关的引用文献作为支持,比如引用[1]和[3]来强调内存优化的有效性。</think>以下是如何使用EasyExcel高效生成包含几十万数据的XLSX文件的逐步解决方案: ### 一、核心实现步骤 1. **分页查询数据** - 采用分段加载策略,每次查询5000-10000数据 - 避免一次性加载全部数据到内存中,防止OOM[^3] ```java public List<DataEntity> queryDataByPage(int pageNo, int pageSize) { // 实际需替换为分页SQL查询 return dataMapper.selectPage((pageNo-1)*pageSize, pageSize); } ``` 2. **配置ExcelWriter** ```java // 使用try-with-resources确保资源释放 try (ExcelWriter excelWriter = EasyExcel.write(fileName, DataEntity.class) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) .build()) { WriteSheet writeSheet = EasyExcel.writerSheet("数据列表").build(); int pageSize = 10000; for (int pageNo = 1; ; pageNo++) { List<DataEntity> dataChunk = queryDataByPage(pageNo, pageSize); if (dataChunk.isEmpty()) break; excelWriter.write(dataChunk, writeSheet); dataChunk.clear(); // 及释放内存 } } ``` ### 二、关键优化策略 1. **内存控制技术** - 使用`SXSSF`模式(自动启用) - 默认保留100数据在内存,超出部分写入临文件[^1] - 调整窗口大小:`.withTempFileWindowSize(500)` 2. **写入方式选择** ```java // 推荐使用异步写入(默认开启) .inMemory(false) // 设置临文件存储路径 .tempFile(new File("/data/temp")) ``` ### 三、最佳实践建议 1. **模板导出优化** ```java // 复用模板样式(引用[4]) ExcelWriter writer = EasyExcel.write(outStream) .withTemplate(templateFile) .registerWriteHandler(new CellStyleStrategy()) .build(); ``` 2. **性能优化配置** - 禁用默认样式:`.ignoreHeadStyle()` - 关闭自动合并:`.autoTrim(false)` - 设置自动列宽:`.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())` ### 四、异常处理 ```java try { // 写入逻辑 } catch (ExcelGenerateException e) { log.error("Excel生成异常", e); // 清理临文件 } finally { if (excelWriter != null) { excelWriter.finish(); } // 删除临文件 } ``` ### 五、扩展方案 1. **海数据分文件存储** - 每50万生成一个sheet - 超过100万生成新文件[^2] ```java if (totalCount % 1000000 == 0) { excelWriter.finish(); createNewWriter(); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值