如何提高读取Excel的效率,NPOI多线程读取详解
如何提高读取Excel的效率
当Excel中的数据量大,达到几十万条,使用Excel文件可能会变得很慢. 以下是一些建议来提高读取Excel的效率:
1. 选择合适的Excel库
在读取Excel文件时, 选择合适的Excel库可以显著提高效率. 一些常用的Excel库包括:
- EPPlus: 用于读写Excel文件的开源库
- NPOI: 用于读写Excel文件的开源库
- Microsoft.Office.Interop.Excel: Microsoft官方提供的Excel库
2. 使用单元格范围
在读取Excel数据时, 不要逐行读取, 而是使用单元格范围. 这种方式可以减少对Excel文件的读取次数, 从而提高读取效率.
以下是一个使用单元格范围的示例:
using (var package = new ExcelPackage(new FileInfo(filePath)))
{ExcelWorksheet worksheet = package.Workbook.Worksheets[worksheetName];var range = worksheet.Cells[2, 1, 50000, 20]; // 选择2-50000行, 1-20列的单元格范围var data = range.Value; // 读取单元格范围中的数据
}
3. 使用多线程
使用多线程可以在读取Excel文件时提高效率. 例如, 可以使用一个线程读取Excel文件, 另一个线程处理数据.
以下是一个使用多线程的示例:
using (var package = new ExcelPackage(new FileInfo(filePath)))
{ExcelWorksheet worksheet = package.Workbook.Worksheets[worksheetName];var range = worksheet.Cells[2, 1, 50000, 20]; // 选择2-50000行, 1-20列的单元格范围// 使用多线程读取单元格范围中的数据var thread = new Thread(() => {var data = range.Value; // 读取单元格范围中的数据// 进行数据处理});thread.Start();
}
4. 关闭Excel应用程序
在读取Excel文件后, 要确保关闭Excel应用程序. 否则, Excel应用程序可能会保留在后台, 导致系统内存占用过高.
以下是一个关闭Excel应用程序的示例:
using (var package = new ExcelPackage(new FileInfo(filePath)))
{ExcelWorksheet worksheet = package.Workbook.Worksheets[worksheetName];var range = worksheet.Cells[2, 1, 50000, 20]; // 选择2-50000行, 1-20列的单元格范围var data = range.Value; // 读取单元格范围中的数据// 关闭Excel应用程序package.Dispose();
}
以上是一些改善读取Excel效率的建议. 根据Excel文件的大小和数据结构, 可以选择不同的方法来提高读取效率.
以下是使用NPOI多线程读取Excel的实例:
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;// ...public void ReadExcelWithMultipleThreads(string filePath, string worksheetName)
{var workbook = new XSSFWorkbook(filePath);var worksheet = workbook.GetSheet(worksheetName);var range = new CellRangeAddress(1, worksheet.LastRowNum, 0, worksheet.GetRow(0).LastCellNum - 1); // 获取单元格范围// 将单元格范围中的数据分块, 每块1000行var chunks = range.Chunks(1000);var tasks = new List<Task>();foreach (var chunk in chunks){var task = Task.Run(() =>{for (var i = chunk.FirstRow; i <= chunk.LastRow; i++){var row = worksheet.GetRow(i);if (row == null) continue;for (var j = chunk.FirstColumn; j <= chunk.LastColumn; j++){var cell = row.GetCell(j);if (cell == null) continue;var cellValue = cell.ToString();// 处理单元格数据}}});tasks.Add(task);}Task.WaitAll(tasks.ToArray());workbook.Close();
}
在此示例中, 使用CellRangeAddress.Chunks()
方法将单元格范围分成多个块, 每个块包含1000行. 然后, 使用Task.Run()
方法将每个块的读取操作分配给一个线程. 最后, 使用Task.WaitAll()
等待所有线程完成后关闭Excel工作簿.
请注意, 在此示例中, 仅使用了一个工作表. 如果要同时读取多个工作表, 则需要根据需要进行修改.
CellRangeAddress.Chunks()
方法在NPOI的2.5.x版本及以上版本中可以使用。
CellRangeAddress
在NPOI中的命名空间为NPOI.SS.Util
。
感谢您的提醒,确实在NPOI的早期版本中没有CellRangeAddress.Chunks()
方法。如果您使用的是早期版本,可以考虑手动分块,或者升级NPOI到2.5.x及以上版本。在NPOI 2.5.x及以上版本中,CellRangeAddress.Chunks()
方法可以用于将单元格范围分成多个块,以便于在多线程环境下高效读取Excel文件。
另外,CellRangeAddress
的命名空间是NPOI.SS.Util
。
以下是手动实现分块的代码,达到Chunks()
方法的效果:
using System.Collections.Generic;
using NPOI.SS.Util;// ...public void ReadExcelManually(string filePath, string worksheetName)
{var workbook = new XSSFWorkbook(filePath);var worksheet = workbook.GetSheet(worksheetName);var range = new CellRangeAddress(1, worksheet.LastRowNum, 0, worksheet.GetRow(0).LastCellNum - 1); // 获取单元格范围var chunkSize = 1000; // 每个块的大小var chunks = new List<CellRangeAddress>();// 将单元格范围分成多个块, 每个块包含chunkSize行for (var i = range.FirstRow; i <= range.LastRow; i += chunkSize){var firstRow = i;var lastRow = i + chunkSize - 1;if (lastRow > range.LastRow) lastRow = range.LastRow;chunks.Add(new CellRangeAddress(firstRow, lastRow, range.FirstColumn, range.LastColumn));}foreach (var chunk in chunks){for (var i = chunk.FirstRow; i <= chunk.LastRow; i++){var row = worksheet.GetRow(i);if (row == null) continue;for (var j = chunk.FirstColumn; j <= chunk.LastColumn; j++){var cell = row.GetCell(j);if (cell == null) continue;var cellValue = cell.ToString();// 处理单元格数据}}}workbook.Close();
}
在此示例中,我们手动将单元格范围分成多个块,每个块包含1000行,然后使用嵌套循环逐个读取单元格,并在每个单元格上执行必要的操作。需要注意的是,手动分块可能需要更多的代码,但是它可以在NPOI的早期版本中使用。
不过,可能需要根据自己的具体情况进行调整。如果你的数据结构与示例代码不同,你可能需要修改块的大小或循环的索引。
相关文章:
如何提高读取Excel的效率,NPOI多线程读取详解
如何提高读取Excel的效率 当Excel中的数据量大,达到几十万条,使用Excel文件可能会变得很慢. 以下是一些建议来提高读取Excel的效率: 1. 选择合适的Excel库 在读取Excel文件时, 选择合适的Excel库可以显著提高效率. 一些常用的Excel库包括: EPPlus: 用于读写Excel文件的开源…...
【算法】【算法杂谈】从1到n的自然数组中,1出现的次数如何计算?
目录 前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本 思考感悟写在最后 前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识! 问题介…...
日常笔记-Flutter build命令参数
Flutter build命令参数 Flutter build命令参数 Flutter build命令参数 flutter build apk 命令支持以下参数: --debug:构建一个调试版本的 APK。--release:构建一个发布版本的 APK。--target-platform<value>:指定目标平台…...

【利用AI让知识体系化】入门Koa框架
思维导图 文章目录 思维导图一、介绍Koa什么是KoaKoa的历史Koa的特点 二、基本使用安装KoaHello World中间件路由错误处理 三、进阶使用静态资源管理Session管理文件上传表单处理HTTPS支持 四、Koa中间件中间件的概念Koa的洋葱模型常用中间件的介绍自定义中间件的编写 五、异步…...
边缘计算:数据采集、清洗与处理的新时代
近日,又一家边缘计算企业成功获得了融资。这家公司名为DeepWalk,致力于提供边缘计算技术,为企业提供安全、快速的数据采集、清洗和处理解决方案。其融资将用于产品研发和市场推广。 DeepWalk成立于2018年,总部位于美国硅谷&#x…...

分区计量管理项目应用
为充分发挥分区计量管理项目在漏损控制的效用,应构建科学完备的应用体系,如下图 分区计量应用体系 1. 基于水量平衡分析的漏损现状评估方法 分区计量管理项目通过监控分析DMA 分区内流量、压力、水质、大用户用水等情况,结合营业抄收系统的营…...
LayoutInflater中inflate()参数解析
1、关于LayoutInflater,它是如何通过 inflate 方法获取到具体View的? 获得LayoutInflater实例的方式有以下三种: LayoutInflater inflater getLayoutInflater();LayoutInflater inflater LayoutInflater.from(this);LayoutInflater infla…...

星河案例ㅣ中国电信 X 冲量在线:基于智算中心的隐私计算应用实践
▏摘要 中国电信是中国三大运营商之一,为响应国家“东数西算”工程的全新数据中心形态,中国电信引入隐私计算平台,对内实现数据确权跟踪、对外实现数据共享交易,盘活中国电信分布在全国不同区域的数据资源和算力资源,…...
开发笔记之:JAVA读取QT QDataStream输出
1.背景 之前的标题是【JAVA反序列化QT序列化内容】,觉得太大太绕,最后改为现在的标题。 本篇内容是对用JAVA解析QT(用的是QDataSteam)所输出(序列化)的内容的小结。 本文涉及类型包括:QString…...

Docker入门实战---修改Docker镜像源
前言 现在大部分互联网公司在实施项目时几乎都会以微服务架构进行落地,那么微服务一旦多了之后就会面临一个如何友好的治理的问题,本人不会重点介绍治理的问题,而是会简单就治理的其中一个环节服务部署运维的问题进行介绍,服务部…...
Java构建高并发高可用的电商平台(静态架构蓝图之剖析架构)
静态架构蓝图 整个架构是分层的分布式的架构,纵向包括CDN,负载均衡/反向代理,web应用,业务层,基础服务层,数据存储层。水平方向包括对整个平台的配置管理部署和监控。 剖析架构 1. CDN CDN系统能够实时…...
SpringBoot核心运行原理解析之------@Conditional条件注解
在SpringBoot核心运行原理解析之------@EnableAutoConfiguration文档中我们完成了自动配置类的读取和筛选,在这个过程中已经涉及了像@ConditionalOnClass这样的条件注解。打开每个自动配置类,都会看到@Conditional或其衍生的条件注解,本节我们来认识下@Conditional注解。 认…...
systemverilog 001 内建数据类型logic
Verilog 有两种基本数据类型,reg 和wire ,都是4值逻辑 0 1 x z,默认值是x。 reg[7:0] m 为无符号 Integer 为有符号32位 time为64位无符号 real为浮点数 systemverilog新引进了logic,logic既可以作为变量(reg功能),也可以作为线网功能(…...

Flink Kafka-Source
文章目录 Kafka Source1. 使用方法2. Topic / Partition 订阅3. 消息解析4. 起始消费位点5. 有界 / 无界模式6. 其他属性7. 动态分区检查8. 事件时间和水印9. 空闲10. 消费位点提交11. 监控12. 安全 Apache Kafka 连接器 Flink 提供了 Apache Kafka 连接器使用精确一次…...

VoxelNeXt:用于3D检测和跟踪的纯稀疏体素网络
VoxelNeXt:Fully Sparse VoxelNet for 3D Object Detection and Tracking 目前自动驾驶场景的3D检测框架大多依赖于dense head,而3D点云数据本身是稀疏的,这无疑是一种低效和浪费计算量的做法。我们提出了一种纯稀疏的3D 检测框架 VoxelNeXt。该方法可以…...

必须了解的内存屏障
目录 一,内存屏障1,概念2,内存屏障的效果3,cpu中的内存屏障 二,JVM中提供的四类内存屏障指令三,volatile 特性1,保证内存可见性定义2,禁止指令重排序3,不保证原子性 一&a…...

【设计模式】状态模式
文章目录 前言状态模式1、状态模式介绍1.1 存在问题1.2 解决问题1.3 状态模式结构图 2、具体案例说明状态模式2.1 不使用状态模式2.2 使用状态模式 3、状态模式总结 前言 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示…...
内核驱动支持浮点数运算
最近在调 iio 下的 ICM42686 驱动,因项目求需要在驱动对加速度和陀螺raw数据进行换算,避免不了浮点运算。内核编译时出现了报错,提示如下: drivers/iio/imu/tdk_icm42686/icm42686.o: In function gyro_data2float: /home/share/…...
Flink学习(一)
分布式计算框架 Java可以使用分布式计算来处理大规模的数据和计算任务,提高计算效率和性能。以下是一些Java分布式计算的例子: Apache Hadoop:Hadoop是一个开源的分布式计算框架,可以处理大规模数据集的分布式存储和处理。它使用Java编写,可以在分布式环境中运行MapReduc…...

linux 常用命令awk
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。 AWK用法 awk 用法:awk pattern {action} files 1.RS, ORS, F…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...