Java EasyExcel 导出报内存溢出如何解决
1.35个Redis企业级性能优化点与解决方案2.对比传统数据库,TiDB 强在哪?谈谈 TiDB 的适应场景和产品能力3.深度长文解析SpringWebFlux响应式框架15个核心组件源码4.Nginx性能调优5招35式不可不知的策略实战5.Java Executors类的9种创建线程池的方法及应用场景分析6.Redis数据结构—跳跃表 skiplist 实现源码分析7.Volatile不保证原子性及解决方案8.吃透 JVM 诊断方法与工具使用9.Java RMI技术详解与案例分析10.通过JUnit源码分析学习编程的奇技淫巧11.什么是依赖倒置原则12.初探 Rust 语言与环境搭建13.为什么用Vite框架?来看它的核心组件案例详解14.Vue状态管理库Pinia详解15.Tomcat的配置文件中有哪些关键的配置项,它们分别有什么作用?16.ECharts实现雷达图详解17.OpenFeign深入学习笔记18.阿里面试让聊一聊Redis 的内存淘汰(驱逐)策略19.除了递归算法,要如何优化实现文件搜索功能20.关于建表字段是否该使用not null这个问题你怎么看?21.三大硬核方式揭秘:Java如何与底层硬件和工业设备轻松通信!22.在 ArkTS 中,如何有效地进行内存管理和避免内存泄漏?23.10款好用的开源 HarmonyOS 工具库24.尝鲜 HarmonyOS NEXT 开发环境搭建25.HarmonyOS NEXT 底部选项卡功能26.HarmonyOS NEXT 开发之ArkTS基础入门27.ArkTS 和仓颉的特性对比与案例28.Spark任务OOM问题如何解决?29.鸿蒙NEXT开发声明式UI是咋回事?30.HarmonyOS NEXT开发之ArkTS自定义组件学习笔记31.如何在鸿蒙 NEXT 中使用 @Builder 装饰器优化 UI 组件的复用?32.鸿蒙 NEXT 如何使用 @Styles 装饰器来优化我的组件代码?33.Java 如何确保 JS 不被缓存34.10月22日纯血鸿蒙正式版发布意味着什么?35.鸿蒙NEXT应用上架与分发步骤详解
36.Java EasyExcel 导出报内存溢出如何解决
37.Java Z 垃圾收集器如何彻底改变内存管理38.聊聊公众号联动扫码登录功能如何实现39.IDEA中通义灵码的使用技巧40.细谈 Linux 中的多路复用epoll41.适合才最美:Shiro安全框架使用心得42.MongoDB面试专题33道解析43.SQL Server 数据太多如何优化44.【项目场景】请求数据时测试环境比生产环境多花了1秒是怎么回事?45.Java灵魂拷问13个为什么,你都会哪些?46.异步编程在ArkTS中具体怎么实现?47.如何理解ArkTS不支持structural typing48.ArkTS四种渲染控制能力49.在ArkTS中,如何优化布局以提高性能?50.ArkUI与MVVM模式的诗和远方51.鸿蒙NEXT开发中如何确保使用 PersistentStorage 存储的数据安全?52.优雅的@ObservedV2和@Trace装饰器53.10个案例告诉你mysql不使用子查询的原因54.鸿蒙 NEXT 开发中,使用公共事件进行进程间通信55.鸿蒙NEXT开发中使用星闪服务56.鸿蒙NEXT使用request模块实现本地文件上传57.玩转 DevEco Studio 5 代码重构功能58.JAVA线程池有哪些队列? 以及它们的适用场景案例59.2025 年,程序员如何找准技术“掘金点”?60.鸿蒙 NEXT 开发中,普通对象跨线程如何传递61.什么是内存泄漏?C++中如何检测和解决?62.使用贪心算法解决最小生成树问题63.如何使用 Python 进行文件读写操作?64.如何在Python中高效地读写大型文件?65.2025春招,Spring 面试题汇总66.2025春招 SpringCloud 面试题汇总67.无需编码5分钟免费部署云上调用满血版DeepSeek68.Python 实现反转、合并链表有啥用?大家好,我是 V 哥。使用EasyExcel进行大数据量导出时容易导致内存溢出,特别是在导出百万级别的数据时。你有遇到过这种情况吗,以下是V 哥整理的解决该问题的一些常见方法,分享给大家,欢迎一起讨论:
EasyExcel大数据量导出常见方法
1. 分批写入
- EasyExcel支持分批写入数据,可以将数据分批加载到内存中,分批写入Excel文件,避免一次性将大量数据加载到内存中。
- 示例代码:
String fileName = "large_data.xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 假设每次写入10000条数据
int batchSize = 10000;
List<Data> dataList;
int pageIndex = 0;
do {
// 分页获取数据
dataList = getDataByPage(pageIndex++, batchSize);
excelWriter.write(dataList, writeSheet);
} while (dataList.size() == batchSize);
// 关闭资源
excelWriter.finish();
2. 设置合适的JVM内存
- 针对大数据导出场景,可以尝试增大JVM的内存分配,例如:
java -Xms512M -Xmx4G -jar yourApp.jar
- 解释:
-Xms512M
:设置初始堆大小为512MB。-Xmx4G
:设置最大堆大小为4GB。
3. 减少数据对象的复杂性
- 导出数据时,尽量简化数据对象,避免不必要的嵌套和多余字段的加载,以减少对象占用的内存空间。
4. 关闭自动列宽设置
- EasyExcel的自动列宽功能会占用大量内存,特别是在数据量较大的情况下。关闭自动列宽可以节省内存。
- 示例代码:
EasyExcel.write(fileName)
.registerWriteHandler(new SimpleWriteHandler()) // 不使用自动列宽
.sheet("Sheet1")
.doWrite(dataList);
5. 使用Stream导出(适合大数据)
- 利用
OutputStream
分批写入数据,减少内存消耗。通过BufferedOutputStream
可以进一步提高性能。 - 示例代码:
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(fileName))) {
ExcelWriter excelWriter = EasyExcel.write(out).build();
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
int pageIndex = 0;
List<Data> dataList;
do {
dataList = getDataByPage(pageIndex++, batchSize);
excelWriter.write(dataList, writeSheet);
} while (dataList.size() == batchSize);
excelWriter.finish();
} catch (IOException e) {
e.printStackTrace();
}
6. 选择合适的数据导出工具
- 如果数据量非常大,可以考虑切换到支持更高性能的导出工具(如Apache POI的
SXSSFWorkbook
),适合导出百万级别数据量,但配置和使用会更复杂。
亮点来了,那要如何使用 POI 的 SXSSFWorkbook来导出百万级别的数据量呢?
Apache POI的SXSSFWorkbook 实现百万级别数据量的导出案例
使用Apache POI的SXSSFWorkbook
可以处理大数据量的Excel导出,因为SXSSFWorkbook
基于流式写入,不会将所有数据加载到内存中,而是使用临时文件进行缓存,这样可以显著减少内存消耗,适合百万级别数据的导出。下面我们来看一个完整的实现示例。
代码如下
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class LargeDataExportExample {
public static void main(String[] args) {
// 文件输出路径
String filePath = "vg_large_data_export.xlsx";
// 导出百万级数据
exportLargeData(filePath);
}
private static void exportLargeData(String filePath) {
// 每次写入的批次大小
final int batchSize = 10000;
// 数据总条数
final int totalRows = 1_000_000;
// 创建SXSSFWorkbook对象,内存中只保留100行,超过的部分会写入临时文件
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
workbook.setCompressTempFiles(true); // 启用临时文件压缩
// 创建工作表
Sheet sheet = workbook.createSheet("Large Data");
// 创建标题行
Row headerRow = sheet.createRow(0);
String[] headers = {"ID", "Name", "Age"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
}
int rowNum = 1; // 数据开始的行号
try {
// 按批次写入数据
for (int i = 0; i < totalRows / batchSize; i++) {
// 模拟获取每批数据
List<Data> dataList = getDataBatch(rowNum, batchSize);
// 将数据写入到Excel中
for (Data data : dataList) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(data.getId());
row.createCell(1).setCellValue(data.getName());
row.createCell(2).setCellValue(data.getAge());
}
// 处理完成一批数据后,可以选择清除缓存数据,防止内存溢出
((SXSSFSheet) sheet).flushRows(batchSize); // 清除已写的行缓存
}
// 将数据写入文件
try (FileOutputStream fos = new FileOutputStream(filePath)) {
workbook.write(fos);
}
System.out.println("数据导出完成:" + filePath);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭workbook并删除临时文件
workbook.dispose();
}
}
/**
* 模拟分页获取数据
*/
private static List<Data> getDataBatch(int startId, int batchSize) {
List<Data> dataList = new ArrayList<>(batchSize);
for (int i = 0; i < batchSize; i++) {
dataList.add(new Data(startId + i, "Name" + (startId + i), 20 + (startId + i) % 50));
}
return dataList;
}
// 数据类
static class Data {
private final int id;
private final String name;
private final int age;
public Data(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
}
来解释一下代码
- SXSSFWorkbook:
SXSSFWorkbook(100)
表示内存中最多保留100行数据,超过的部分会写入临时文件,节省内存。 - 批次处理:通过
batchSize
控制每批次写入的数据量,以减少内存消耗。totalRows
设置为1,000,000表示导出100万条数据。 - 模拟数据生成:
getDataBatch
方法模拟分页获取数据,每次返回一批数据。 - 清除缓存行:每次写入一批数据后,通过
flushRows(batchSize)
将缓存的行从内存中清除,以控制内存占用。 - 压缩临时文件:
workbook.setCompressTempFiles(true)
启用临时文件压缩,进一步减少磁盘空间占用。
需要注意的事项
- 临时文件:SXSSFWorkbook会在系统临时文件夹中生成临时文件,需要确保磁盘空间足够。
- 资源释放:完成数据写入后需要调用
workbook.dispose()
以清理临时文件。 - 性能优化:可根据机器内存调整
batchSize
和SXSSFWorkbook
缓存行数,避免频繁刷新和内存溢出。
本文来自博客园,作者:威哥爱编程,转载请注明原文链接:https://www.cnblogs.com/wgjava/p/18510650
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签