【✅如何针对大Excel做文件读取?】

在这里插入图片描述

✅如何针对大Excel做文件读取?

  • 🟩如何针对大Excel做文件读取
    • 🟩XSSFWorkbook文件读取
    • 🟩EasyExcel文件读取
  • ✅扩展知识
    • 🟩 EasyExcel简介
    • 🟩EasyExcel 为什么内存占用小?

🟩如何针对大Excel做文件读取

在POI中,提供了SXSSFWorkbook,通过将部分数据写入磁盘上的临时文件来减少内存占用。但是SXSSFWorkbook只能用于文件写入,但是文件读取还是不行的,就像我们前面分析过的,Excel的文件读取还是会存在内存溢出的问题的。

🟢参考本人博客文件处理专栏: 什么是POI,为什么他会导致内存溢出?

🟢参考本人博客文件处理专栏: POI如何做大文件的写入?

那如果要解决这个问题,可以考虑使用EasyExcel。

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、
内存的等因素的情况下,快速完成Excel的读、写等功能。

关于使用XSSFWorkbook和EasyExcel的文件读取,我这里也做了个内存占用的对比:

🟩XSSFWorkbook文件读取

读取一个27.3MB的文件(文件的生成代码📑✅链接: POI如何做大文件的写入)

package excel.read;import org.apache.poi.ss .usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class XSSFExcelReadTest {public static void main(String[] args) {// 指定要读取的文件路径String filename = "example.xlsx";try (FileInputStream fileInputStream = new FileInputStream(new File(filename))) {// 创建工作簿对象Workbook workbook = new XSSFWorkbook(fileInputStream);//获取第一个工作表Sheet sheet = workbook.getSheetAt(0);// foreach 遍历所有行for (Row row : sheet) {// 遍历所有单元格for (Cell cell : row) {// 根据不同数据类型处理数据switch (cel1.getCel1Type()) {case STRING:System.out.print(cell.getstringCellValue() + " t");break;case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {System.out.print(cell.getDateCellValue() + "t");} else {System.out.print(cell.getNumericCellValue() + " t”);}break;case BOOLEAN:System.out.print(cell.getBooleanCellValue() + " t");break;case FORMULA:System.out.print(cell.getCellFormula() + "t");break;default:System.out.print("");}}System.out.println();//换行}}catch (IOException e)  {e.printStackTrace();}}
}

同样使用Arthas查看内存占用情况:

在这里插入图片描述
占用内存1000+M

🟩EasyExcel文件读取

package excel.read;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener:public class EasyExcelReadTest {public static void main(Stringl] args) {// 指定要读取的文件路径String filename = "example.xlsx";EasyExcel.read(filename, new PrintDataListener()).sheet().doRead();}
}// 监听器,用于处理读取到的数据
class PrintDatalistener implements ReadListener<Object> {@Overridepublic void invoke(Object data, AnalysisContext context) {//处理每一行的数据System.out.println(data) ;}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 所有数据解析完成后的操作}@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {//处理读取过程中的异常}
}

同样使用Arthas查看内存占用情况:

在这里插入图片描述
内存占用只有不到100MB。

✅扩展知识

🟩 EasyExcel简介

EasyExcel是一款软件程序,允许用户创建、编辑和分析电子表格。它设计成用户友好和直观,使得所有技能水平的用户都能轻松处理数据。EasyExcel提供了广泛的功能,包括进行计算、创建图表和图形以及在表格中组织数据的能力。它还支持各种文件格式,如.xls和.xlsx,使用户能够方便地导入和导出来自其他应用程序的数据。总体而言,EasyExcel是一种多功能的工具,用于管理和操作电子表格格式的数据。

🟩EasyExcel 为什么内存占用小?

EasyExcel是一款基于POI(Apache开源的Java类库)开发的Excel操作工具。相比于传统的操作Excel的方式,EasyExcel采用了一种新的处理方式,即将Excel数据转化为对象列表然后进行操作。这种方式减少了对内存的占用,提高了数据处理的效率。

具体的来说,EasyExcel在内存占用方面有以下几个优势:

1. 逐行读写:EasyExcel通过逐行读写的方式操作Excel,即一次只读取或写入一行数据,而不是一次性读取或写入整个文件。这样可以大大减少对内存的占用。

2. 分段读写:当需要处理大文件时,EasyExcel可以将文件拆分成多个小段进行读写,每次只处理一小段数据,将读写的内存压力均匀分散,降低了内存的占用。

3. 内存缓冲区:EasyExcel内部使用了内存缓冲区来存储读取或写入的数据,通过合理控制缓冲区的大小,可以有效地减少对内存的占用。

4. 高效的数据处理算法:EasyExcel内部采用了高效的数据处理算法,例如使用零拷贝技术来提高数据读写的速度,减少对内存的占用。

综上所述,EasyExcel通过优化读写方式、使用内存缓冲区和高效的数据处理算法等手段,可以实现在相同数据量的情况下占用更小的内存空间,提高数据处理的效率。

参考代码,展示了如何使用EasyExcel读取Excel文件并计算内存占用。

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.ReadListener;import java.io.File;public class EasyExcelMemoryDemo {public static void main(String[] args) {String filePath = "path/to/excel/file.xlsx";// 创建一个监听器,用于统计内存占用ReadListener<Object> listener = new ReadListener<>() {private long startMemory;@Overridepublic void invoke(Object data, AnalysisContext context) {if (context.readRowHolder().getRowIndex() == 0) {// 记录读取第一行数据时的内存占用startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 读取完所有数据后,计算内存占用的差值long endMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();long memoryUsage = endMemory - startMemory;System.out.println("Excel文件读取完毕");System.out.println("内存占用差值:" + memoryUsage + " bytes");}};// 读取Excel文件EasyExcel.read(new File(filePath)).registerReadListener(listener).sheet().doRead();}
}

输出Excel文件读取完毕后的内存占用差值。相比于使用传统的POI工具,使用EasyExcel读取Excel文件时,内存占用会更小。

EasyExcel是一个Java库,用于简化Excel文件的读写操作。相较于Apache POI等传统Excel处理库,EasyExcel具有内存占用小的优势。这主要归功于EasyExcel的底层实现和数据处理方式。

展示:

import com.alibaba.excel.EasyExcel;  
import com.alibaba.excel.ExcelReader;  
import com.alibaba.excel.ExcelWriter;  
import com.alibaba.excel.context.AnalysisContext;  
import com.alibaba.excel.event.AnalysisEventListener;  
import com.alibaba.excel.metadata.BaseRowModel;  
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;  
import com.alibaba.excel.write.metadata.WriteSheet;  
import com.alibaba.excel.write.metadata.WriteTable;  
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;  import java.util.ArrayList;  
import java.util.List;  /***@author 昕宝爸爸爱编程*@date 23/12/14*/
public class AdvancedMemoryOptimizedExample {  public static void main(String[] args) {  String inputFileName = "input_example_complex.xlsx";  String outputFileName = "output_example_complex.xlsx";  int pageSize = 1000;  int sheetCount = 3; // 定义要写入的Sheet数量  int totalPage = 0; // 总页数变量,用于动态计算总页数  // 创建数据模型类,用于存储读取到的数据  class DataModel extends BaseRowModel {  private String field1; // 字段1  private int field2; // 字段2  // 其他字段...  // 对应的getter和setter方法...  }  // 内存优化示例:读取Excel文件并分页处理  List<DataModel> dataList = new ArrayList<>(); // 创建一个空的列表用于存储数据  ExcelReader excelReader = EasyExcel.read(inputFileName, new NoModelDataListener<DataModel>()).build(); // 使用自定义的DataModel类作为监听器的参数类型  ReadSheet readSheet = EasyExcel.readSheet(pageSize).build(); // 设置读取时的分页参数  excelReader.read(readSheet, new AnalysisEventListener<DataModel>() { // 使用自定义的DataModel类作为事件处理接口的参数类型  @Override  public void invoke(DataModel data, AnalysisContext context) {  // 在invoke方法中进行自定义数据处理逻辑,比如将读取到的数据存储到数据库等操作...  dataList.add(data); // 这里仅作示例,将读取到的数据添加到列表中,实际应用中可能需要进行其他处理  }  @Override  public void doAfterAllAnalysed(AnalysisContext context) {  // 处理读取完所有数据后的逻辑...可以在这里添加一些操作,比如关闭资源等  totalPage = context.getHead().getSheet().getVirtual(context).getTotalRowNum() / pageSize + 1; // 动态计算总页数,用于后续写入操作时使用  }  }); // 开始读取数据,并传入监听器进行数据处理  excelReader.finish(); // 读取完成后关闭Excel读取器  // 内存优化示例:写入Excel文件并自定义样式和分页写入策略  WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 创建一个自定义的单元格样式对象,可以根据需要设置样式属性  HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(null, contentWriteCellStyle); // 创建一个水平单元格样式策略对象,用于设置单元格样式策略  ExcelWriterBuilder writerBuilder = EasyExcel.write(outputFileName); // 创建Excel写入器构建器对象,用于配置写入参数和设置样式策略等  writerBuilder.registerWriteHandler(horizontalCellStyleStrategy); // 注册之前创建的样式策略对象到写入器中,用于设置单元格样式策略  ExcelWriter excelWriter = writerBuilder.build(); // 创建Excel写入器实例,用于实际写入操作  for (int i = 1; i <= sheetCount; i++) { // 根据定义的Sheet数量循环创建多个Sheet进行写入操作  WriteSheet writeSheet = EasyExcel.writerSheet("Sheet" + i).build(); // 创建多个Sheet进行写入操作,每个Sheet名称分别为"Sheet1"、"Sheet2"等,可以根据需要自定义Sheet名称和数量等参数  excelWriter.write(dataList, writeSheet, totalPage); // 将之前读取到的数据写入到输出文件中,并传入Sheet参数和样式策略等参数,同时传入动态计算的总页数参数,用于分页写入操作时使用  } // 循环写入多个Sheet数据到输出文件中,并传入对应的样式策略和总页数参数等

主要通过以下几个方式来节省内存:

使用分页读取和写入:通过设置pageSize参数,将数据分页读取和写入,可以减少一次性读取和写入的数据量,从而减少内存占用。

使用数据模型类:通过创建一个数据模型类(DataModel),将读取到的数据存储到该类的对象中,而不是直接存储到原始数据类型列表中。这样可以避免为每个数据项创建过多的对象,从而减少内存占用。

使用水平单元格样式策略:通过创建一个水平单元格样式策略对象(HorizontalCellStyleStrategy),并将样式策略注册到Excel写入器中。该策略可以根据单元格的内容自动应用样式,从而减少手动设置样式所带来的内存开销。

动态计算总页数:在读取完所有数据后,通过调用context.getHead().getSheet().getVirtual(context).getTotalRowNum()方法,动态计算总页数。这样可以避免在循环中多次计算总页数,从而减少内存占用。

综上所述,通过分页读取和写入、使用数据模型类、使用水平单元格样式策略以及动态计算总页数等方式,实现了内存的优化使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

欧盟健身单车出口BS EN ISO 20957安全报告测试

固定的训练器材.第10部分:带固定轮或无自由飞轮的训练自行车.附加特定安全要求和试验方法 作为欧洲固定式健身器材&#xff08;儿童用固定式健身器材不在此范围&#xff09;通用安全要求和测试方法的标准&#xff0c;涉及固定式健身器材精度、使用场所分类定义、稳定性、安全间…

Amazon CodeWhisperer 体验

文章作者&#xff1a;jiangbei 1. CodeWhisperer 安装 1.1 先安装 IDEA&#xff0c;如下图&#xff0c;IDEA2022 安装为例&#xff1a; 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者…

我的创作纪念日-IT从业者张某某

机缘 勿忘初心&#xff0c;牢记使命&#xff0c;我成为创作者的初心是什么呢&#xff1f;时间有些久了&#xff0c;回头看下自己的第一篇博客&#xff0c;还是略显青涩的&#xff0c;有种不忍直视的感觉。 我的第一篇博客&#xff0c;应该是想记录下工作中的一个演示项目&…

[Bond的杂货铺] CERTIFIED KUBERNETES ADMINISTRATOR 到货咯

Its been a long time. Mr. K8s. 既然接触了这么多年&#xff0c;2018年在1.11版就认识了&#xff0c;如今都到了1.28&#xff0c;拖到连与docker都分手了。所以&#xff0c;考一个&#xff0c;很合理吧。 分数是88&#xff0c;隐约感觉是因为有几处因为实在不想把光标移来移…

挑战内网安全难题,迅软DSE如何以管控之力助您一臂之力?

随着信息化程度的提高&#xff0c;政企单位面临更加复杂和不可控的内网安全问题。由于缺乏有效技术手段和完善的管理机制&#xff0c;企业内网管理长期处于被动状态&#xff0c;而在发生数据安全事件后的快速处置能力也相对薄弱。 迅软DSE桌面管理系统成为解决方案&#xff0c…

【Java】基于fabric8io库操作k8s集群实战(pod、deployment、service、volume)

目录 前言一、基于fabric8io操作pod1.1 yaml创建pod1.2 fabric8io创建pod案例 二、基于fabric8io创建Service&#xff08;含Deployment&#xff09;2.1 yaml创建Service和Deployment2.2 fabric8io创建service案例 三、基于fabric8io操作Volume3.1 yaml配置挂载存储卷3.2 基于fa…

HBuilder X将Vue打包APP返回上一页退出问题、清除缓存页面历史防止返回登录页(上一页)、以及状态栏颜色切换

目录 一、返回上一页退出问题 二、清除缓存页面历史防止返回上一页 三、状态栏颜色切换 一、返回上一页退出问题 1.首先重新认识一下vue的页面跳转&#xff0c;这里我只说常用到的两个 goSkip(){//直接跳转this.$router.push(/test);this.$router.replace(/test);//带参数跳…

『 Linux 』重新理解挂起状态

文章目录 &#x1f984; 前言新建状态 &#x1f40b;挂起状态 &#x1f40b;唤入唤出 &#x1f40b;进程与操作系统间的联系 &#x1f40b; &#x1f984; 前言 『 Linux 』使用fork函数创建进程与进程状态的查看中提到了对挂起状态的一个理解&#xff1b; ​ 挂起状态相比于其…

LearnDash LMS ProPanel在线学习系统课程创作者的分析工具

点击阅读LearnDash LMS ProPanel在线学习系统课程创作者的分析工具原文 LearnDash LMS ProPanel在线学习系统课程创作者的分析工具通过整合报告和作业管理来增强您的 LearnDash 管理体验&#xff0c;使您能够发送特定于课程的通信&#xff0c;并显示课程的实时活动&#xff01…

Postgresql在Windows中使用pg_dump实现数据库(指定表)的导出与导入

场景 Windows中通过bat定时执行命令和mysqldump实现数据库备份&#xff1a; Windows中通过bat定时执行命令和mysqldump实现数据库备份_mysqldump bat-CSDN博客 Windows上通过bat实现不同数据库之间同步部分表的部分字段数据&#xff1a; Windows上通过bat实现不同数据库之间…

YOLOv5改进 | SPPF | 将RT-DETR模型AIFI模块和Conv模块结合替换SPPF(全网独家改进)

一、本文介绍 本文给大家带来是用最新的RT-DETR模型中的AIFI模块来替换YOLOv5中的SPPF。RT-DETR号称是打败YOLO的检测模型&#xff0c;其作为一种基于Transformer的检测方法&#xff0c;相较于传统的基于卷积的检测方法&#xff0c;提供了更为全面和深入的特征理解&#xff0c…

【Hadoop面试】HDFS读写流程

HDFS&#xff08;Hadoop Distributed File System&#xff09;是GFS的开源实现。 HDFS架构 HDFS是一个典型的主/备&#xff08;Master/Slave&#xff09;架构的分布式系统&#xff0c;由一个名字节点Namenode(Master) 多个数据节点Datanode(Slave)组成。其中Namenode提供元数…

neuq-acm预备队训练week 10 P1525 [NOIP2010 提高组] 关押罪犯

解题思路 本题用并查集的方法 AC代码 #include <bits/stdc.h> using namespace std; int f[55555]; struct S {int a,b,c;friend inline bool operator<(S a, S b){return a.c>b.c;} } d[100000];int find(int x) {return f[x]x? x:(f[x]find(f[x])); }int mai…

易点易动固定资产管理系统——提升固定资产管理透明度和可靠性

通过全面的资产跟踪、准确的数据记录和实时的报告分析&#xff0c;易点易动系统为企业提供了全新的固定资产管理解决方案&#xff0c;帮助企业实现高效、精确的资产管理&#xff0c;提高运营效率&#xff0c;降低风险&#xff0c;实现可持续发展。 固定资产是企业重要的资源和投…

2019系统修复

修改启动顺序 尝试从最后一次正确配置启动 然后删除最后安全的程序。 准备usb系统盘 用系统引导盘进入命令提示符 chkdsk c: 在只读模式看下是否磁盘有问题。 sfc /scannow命令 在管理员命令提示符窗口输入&#xff1a;sfc /scannow命令。 复制&#xff1a;sfc /scanno…

倚力未来:人工智能智能辅助医疗的前景与挑战

导言 人工智能在医疗领域的应用正迅速发展&#xff0c;为医疗行业带来了新的可能性。本文将深入探讨人工智能在医疗中的智能辅助应用&#xff0c;以及这一趋势面临的前景和挑战。智慧医疗是指通过先进的信息技术&#xff0c;如人工智能、物联网、大数据等&#xff0c;实现医疗数…

使用Pytorch从零开始构建StyleGAN2

这篇博文是关于 StyleGAN2 的&#xff0c;来自论文Analyzing and Improving the Image Quality of StyleGAN&#xff0c;我们将使用 PyTorch 对其进行干净、简单且可读的实现&#xff0c;并尝试尽可能地还原原始论文。 如果您没有阅读 StyleGAN2 论文。或者不知道它是如何工作…

如何戒掉懒惰这个坏习惯?

懒惰是一个常见的坏习惯&#xff0c;它会阻碍我们的进步&#xff0c;影响我们的生活质量。然而&#xff0c;戒掉懒惰并不容易&#xff0c;需要付出一定的努力和毅力。本文将介绍几种方法来戒掉懒惰习惯&#xff0c;帮助你走上一个积极向上的道路。首先&#xff0c;认识到懒惰的…

【MATLAB】数据拟合第11期-基于粒子群迭代的拟合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 基于粒子群迭代的拟合算法是一种优化技术&#xff0c;它基于粒子群优化算法&#xff08;PSO&#xff09;的基本思想。该算法通过群体中个体之间的协作和信息共享来寻找最优解。 在基于粒…

iPhone16:首款AI iPhone?

随着科技水平的不断发展&#xff0c;智能手机逐渐成为人们最依赖的电子产品之一。为能够满足用户需求&#xff0c;手机的硬件、外观设计与性能飞速提升&#xff0c;这也导致智能手机市场快速进入到瓶颈期。 为了能够带来更优秀的表现&#xff0c;苹果可能会为iPhone 16系列带来…