如何解决Java EasyExcel 导出报内存溢出
如何解决Java EasyExcel 导出报内存溢出
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
缓存行数,避免频繁刷新和内存溢出。
作为程序员,持续学习和充电非常重要,作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。低代码也是一个值得我们深入探索的领域,让我们拭目以待,它将给前端世界带来怎样的变革,推荐一个低代码工具。
应用地址:www.jnpfsoft.com
开发语言:Java/.net
这是一个基于Flowable引擎(支持java、.NET),已支持MySQL、SqlServer、Oracle、PostgreSQL、DM(达梦)、 KingbaseES(人大金仓)6个数据库,支持私有化部署,前后端封装了上千个常用类,方便扩展,框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用。
至少包含表单建模、流程设计、报表可视化、代码生成器、系统管理、前端 UI 等组件,这种情况下我们避免了重复造轮子,已内置大量的成熟组件,选择合适的组件进行集成或二次开发复杂功能,即可自主开发一个属于自己的应用系统。
相关文章:
如何解决Java EasyExcel 导出报内存溢出
如何解决Java EasyExcel 导出报内存溢出 EasyExcel大数据量导出常见方法 1. 分批写入 EasyExcel支持分批写入数据,可以将数据分批加载到内存中,分批写入Excel文件,避免一次性将大量数据加载到内存中。 示例代码: String fileNa…...
[产品管理-91]:产品经理的企业运营的全局思维-1
目录 前言:企业架构图 产品经理的企业运营全局思维 1、用户 - 用户价值与体验:真正的需求,真正的问题,一切的原点 2、大势 - 顺应宏观大势:政策趋势、行业趋势、技术趋势 3、市场 - 知己知彼:市场调研…...
学习笔记——stm32看门狗
目录 一、WDG简介 二、IWDG框图 2.1独立看门狗结构 2.2键寄存器 2.3超时时间 三、WWDG框图 3.1窗口看门狗结构 3.2WWDG时序图 3.3最早、最晚时间 四、IWDG和WWDG对比 五、IWDG相关库函数和应用 5.1相关库函数 5.2应用 六、WWDG相关库函数和应用 6.1相关库函数 6…...
2411rust,cargo清理缓存
原文 Cargo最近在晚间通道上取得了一个不稳定的功能(从nightly-2023-11-17开始),它可自动清理Cargo主目录中的缓存内容. 总之,请求使用晚间通道的人启用此功能,并在Cargo问题跟踪器上报告问题.要启用它,请在你的一般在~/.cargo/config.toml或%USERPROFILE%\.cargo\config.tom…...
高级java每日一道面试题-2024年11月19日-基本篇-获取一个类Class对象的方式有哪些?
如果有遗漏,评论区告诉我进行补充 面试官: 获取一个类Class对象的方式有哪些? 我回答: 在 Java 中,获取一个类的 Class 对象有多种方式。这些方式各有优缺点,适用于不同的场景。以下是常见的几种方法及其详细解释: 1. 使用 new 关键字实…...
Vue 3与TypeScript集成指南:构建类型安全的前端应用
在Vue 3中使用TypeScript,可以让你的组件更加健壮和易于维护。以下是使用TypeScript与Vue 3结合的详细步骤和知识点: 1. 环境搭建 首先,确保你安装了Node.js(推荐使用最新的LTS版本)和npm或Yarn。然后,安…...
可视化建模与UML《活动图实验报告》
你当像鸟飞往你的山。 一、实验目的: 1、熟悉活动图的基本功能和使用方法。 2、掌握使用建模工具软件绘制协作图的方法 二、实验环境: window7 | 10 | 11 EA15 三、实验内容: <1>绘制学生选课系统中添加课程(Add Course)用例的活动图…...
接雨水
接雨水 1、 题目描述2、解题思路 1、 题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 2、解题思路 本题使用了双指针,根据下图可以得出,下标 i 处能接的雨水量由左边…...
i春秋-签到题
练习平台地址 竞赛中心 题目描述 题目内容 点击GUESS后会有辨识细菌的选择题 全部完成后会有弹窗提示 输入nickname后提示获得flag F12检查 元素中没有发现信息 检查后发现flag在控制台中 flag flag{663a5c95-3050-4c3a-bb6e-bc4f2fb6c32e} 注意事项 flag不一定要在元素中找&a…...
Selenium + 数据驱动测试:从入门到实战!
引言 在软件测试中,测试数据的多样性和灵活性对测试覆盖率至关重要。而数据驱动测试(Data-Driven Testing)通过将测试逻辑与数据分离,极大地提高了测试用例的可维护性和可扩展性。本文将结合Selenium这一流行的测试工具࿰…...
考研倒计时30天丨和西电一起向前!再向前!
上岸后 就能来 西安电子科技大学 和学长学姐一起吃饭,XDU食堂都有你想要的一切 ①、海棠篇:海棠新生初入校园,还在犹豫吃什么?宿舍楼边的海棠餐厅物美价廉,满足你一日三餐的需求与期盼! 俗话说:…...
json数组写入文件每行一条数据
我们知道将json或json数组写入文件,一般是用JSON.stringify先将json或json数组转成字符串,再写入文件。JSON.stringify()的语法是这样的:JSON.stringify(value[, replacer[, space]]) JSON.stringify(value)调用则不带空格tab换行等分隔符&am…...
EasyExcel并行导出多个excel文件并压缩下载
EasyExcel并行导出多个excel文件并压缩下载 在SpringBoot应用中,采用同步方式导出Excel文件会导致服务器在生成文件期间阻塞,特别是在处理大量数据时,这种效率较低的方法会严重影响性能。为了解决这个问题,可以采用以下改进措施:首先将导出的数据进行拆分,然后利用Compl…...
hadoop3.x 新特性
hadoop3.x 新特性 FeaturesHadoop 2.xHadoop 3.xMinimum Required Java VersionJDK 6 and above.JDK 8 is the minimum runtime version of JAVA required to run Hadoop 3.x as many dependency library files have been used from JDK 8.Fault ToleranceFault Tolerance is …...
单片机智能家居火灾环境安全检测-分享
目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 电路图采用Altium Designer进行设计: 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 传统的火灾报警系统大多依赖于简单的烟雾探测器或温度传感器,…...
241117学习日志——[CSDIY] [ByteDance] 后端训练营 [05]
CSDIY:这是一个非科班学生的努力之路,从今天开始这个系列会长期更新,(最好做到日更),我会慢慢把自己目前对CS的努力逐一上传,帮助那些和我一样有着梦想的玩家取得胜利!!&…...
Oracle 19C 安装RAC磁盘投票失败
ORACLE 19C 安装RAC第二个节点报错,没有找到足够的 voting 文件(投票磁盘) 1、磁盘投票失败分析 1.1、02节点报错日志 CRS-4123: Starting Oracle High Availability Services-managed resources CRS-2672: Attempting to start ora.mdnsd…...
vulfocus在线靶场:骑士cms_cve_2020_35339:latest 速通手册
目录 一、启动环境,访问页面,ip:端口号/index.php?madmin,进入后台管理页面,账号密码都是adminadmin 二、进入之后,根据图片所示,地址后追加一下代码,保存修改 三、新开标签页访问:①ip:端…...
【Linux内核深度解析】TCP协议栈之tcp_recvmsg
tcp_recvmsg 是 Linux 内核中用于处理 TCP 套接字接收数据的核心函数。它的主要任务是从接收队列中读取数据并将其复制到用户空间。 函数原型 int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int nonblock, int flags, int *addr_le…...
android-studio-4.2下载 、启动
下载 分享一个国内的android studio网站,可以下载SDK和一些Android studio开发工具 https://www.androiddevtools.cn/ 启动 JAVA_HOME/app/zulu17.48.15-ca-jdk17.0.10-linux_x64/ /app5/android-studio-home/android-studio-ide-201.6568795-linux-4.2C1/bin/s…...
Excel——宏教程(2)
Excel——宏教程(2) 一)、处理单元格 1、直接赋值与引用 将变量、常量值直接赋给单元格、或将单元格的值直接赋给变量、常量,这是在excel中最简单的单元格赋值及引用方法。 如下例将工作表"Sheet1"A1单元格的值赋给Integer变量I,并将I1的值…...
React Native 全栈开发实战班 - 性能与调试之打包与发布
在完成 React Native 应用的开发与性能优化后,下一步就是将应用打包并发布到各大应用市场,如 Apple App Store 和 Google Play Store。本章节将详细介绍 React Native 应用的打包与发布流程,包括 Android 和 iOS 平台的打包步骤、签名配置、发…...
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
最近在做一个与激光器用串口进行通讯的程序文档中要求将频率参数以3个字节的方式进行发送。这里记录一下过程。以便以后再有类似问题时可以快速解决。 /// <summary>/// 设置频率/// </summary>/// <param name"sender"></param>/// <par…...
Win11下载和配置VSCode(详细讲解)
配置VSCode需要的工具: 一、MinGW-w64 二、Visual Studio Code 一、MinGW-w64下载 1、下载 MinGW官网地址: Downloads - MinGW-w64 直链下载: 下载 mingw-w64-install.exe (MinGW-w64 - 适用于 32 位和 64 位 Windows&#…...
基于Multisim的多路智力竞赛抢答器设计与仿真
(1)设计一个8路智力竞赛抢答器,主持人可控制系统的清零和抢答的开始,控制电路可实现最快抢答选手按键抢答的判别和锁定功能,并禁止后续其他选手抢答。 (2)抢答选手确定后给出一声音响的提示和选手编号的显示,抢答选手的编号显示保持到系统被清零为止。 …...
Three.js 闪电效果
闪电shader const shader new THREE.ShaderMaterial({uniforms: {iTime: this.iTime,color: { value: new THREE.Color("#D2F8FE") },},vertexShader: /* glsl */ varying vec2 vUv;varying float normalizeY;void main() {// vUv (uv * 2. - 2.) * vec2(0.3,2.);…...
高效序列化工具(1)-----Protobuf
目录 1.Protobuf Protobuf 的特点 工作原理 Protobuf 与 JSON、XML 的对比 2.protobuf语法 1.数据类型 2.消息 3.枚举 4.嵌套消息 5.重复字段 6.默认值 7.其他类型 1.oneof类型 2.any类型 8.文件组织 3.protobuf命令 1.常见命令 选项: 1. --proto_…...
湛江市社保卡申领指南:手机获取电子照片回执单号
在湛江市,社保卡的申领流程已经实现了数字化,为市民带来了极大的便利。特别是通过手机获取数码照片回执单号,这一环节更是简化了申领过程。今天,我们将详细介绍如何不去照相馆,利用手机来获取数码照片回执单号…...
HTML5实现剪刀石头布小游戏(附源码)
文章目录 1.设计来源1.1 主界面1.2 皮肤风格1.2 游戏中界面 2.效果和源码源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/143798520 HTM…...
TypeScript之常见类型
常见类型(Everyday Types) 本章我们会讲解 JavaScript 中最常见的一些类型,以及对应的描述方式。注意本章内容并不详尽,后续的章节会讲解更多命名和使用类型的方式。 类型可以出现在很多地方,不仅仅是在类型注解 (type annotations)中。我们不仅要学习类型本身,也要学习…...
MacOS java多版本安装与管理-sdkman
安装sdkman curl -s "https://get.sdkman.io" | bashsource "$HOME/.sdkman/bin/sdkman-init.sh"sdk version正常出现sdkman版本号就安装成功了 # 安装java # 安装java8 sdk install java 8.0.412.fx-zulu建议和上述一样安装 fx-zulu 的jdk,…...
NLP论文速读(多伦多大学)|利用人类偏好校准来调整机器翻译的元指标
论文速读|MetaMetrics-MT: Tuning Meta-Metrics for Machine Translation via Human Preference Calibration 论文信息: 简介: 本文的背景是机器翻译(MT)任务的评估。在机器翻译领域,由于不同场景和语言对的需求差异&a…...
20241121 android中树结构列表(使用recyclerView实现)
1、adapter-item的布局 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"wrap_content&…...
达索系统亮相第三十一届中国汽车工程学会年会暨展览会
伴随着改革开放以及中国入世WTO,三十多年来,中国汽车产销已经成为世界最大的单一市场而独占鳌头。近十年来,另辟蹊径的中国汽车产业人在新能源汽车赛道上引领了一波又一波令全球惊艳的创新成就,成为最为靓丽的新出口三大件的头牌。…...
Python网络爬虫实践案例:爬取猫眼电影Top100
以下是一个Python网络爬虫的实践案例,该案例将演示如何使用Python爬取猫眼电影Top100的电影名称、主演和上映时间等信息,并将这些信息保存到TXT文件中。此案例使用了requests库来发送HTTP请求,使用re库进行正则表达式匹配,并包含详…...
ROSSERIAL与Arduino IDE交叉开发(UBUNTU环境,包含ESP32、arduino nano)
ROSSERIAL与Arduino IDE交叉开发 一、简介二、安装1、Ubuntu下的Arduino IDE安装 **针对ESP32报错问题原因溯源和修改**三、运行结点 一、简介 这个教程展示在ubuntu环境下如何利用Arduino IDE配合rosserial开发机器人部件。通过Arduino IDErosserial实现arduino/esp32开发板通…...
爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具
第三节:使用Postman和浏览器开发者工具 在网络爬虫开发过程中,我们经常需要对HTTP请求进行测试、分析和调试。Postman和浏览器开发者工具(特别是Network面板和Console面板)是两种最常用的工具,能够帮助开发者有效地捕…...
ceph 18.2.4二次开发,docker镜像制作
编译环境要求 #需要ubuntu 22.04版本 参考https://docs.ceph.com/en/reef/start/os-recommendations/ #磁盘空间最好大于200GB #内存如果小于100GB 会有OOM的情况发生,需要重跑 目前遇到内存占用最高为92GB替换阿里云ubuntu 22.04源 将下面内容写入/etc/apt/sources.list 文件…...
游戏引擎学习第19天
介绍 这段内容描述了开发者在进行游戏开发时,对于音频同步和平台层的理解和调整的过程。以下是更详细的复述: 开发者表达了他希望今天继续进行的工作内容。他提到,昨天他讲解了一些关于音频的内容,今天他想稍微深入讲解一下他正…...
简单实现vue2响应式原理
vue2 在实现响应式时,是根据 object.defineProperty() 这个实现的,vue3 是通过 Proxy 对象实现,但是实现思路是差不多的,响应式其实就是让 函数和数据产生关联,在我们对数据进行修改的时候,可以执行相关的副…...
TypeScript 中扩展现有模块的用法
declare module 是 TypeScript 中用于扩展现有模块的特性。它允许开发者在已有模块的基础上,添加新的功能(比如扩展接口、添加类型声明等)。通过 declare module,可以将额外的声明合并到原模块中。以下是用法详解: 用…...