文章目录

  • Excel深度解析历程
    • 故事背景
    • 技术选型方案
      • 一、 直接采用现成的框架
      • 二、 自己处理解析
    • 遇到的困难
    • 升级的思路
      • 一、大胆的创想
      • 二、深度解析实践
        • 第一步
        • 第二步
        • 第三步
        • 性能测试
        • 性能提升空间
    • 小结

Excel深度解析历程

故事背景

      最近公司分配了一个任务,里面就有各种各样的文件解析,由于公司之前也找过外包公司开发过同样的代码,但是xlsx格式的文件接口响应速度惨不忍睹,下面用的全部都是同一个文件测试,文件大小7.8M,行数2.1w行,之前的版本,执行当前文件的计算耗时12秒!!!于是乎,我就成了重新开发那个模块的“大冤种”;

技术选型方案

一、 直接采用现成的框架

  1. 可以使用easypoi框架,简单易用,详情可以查看我的另一篇 博客[链接]  https://blog.csdn.net/q82682810X/article/details/114314333/ ,不出意外的话,应该旧版本就采用的是这种懒人模式,代码敲起来是快了,系统得垮了。2. 使用阿里提供的easyExcel工具类,sax模式读取,性能倍感提升!3. 使用apache提供的excel解析基础类,进行解析

二、 自己处理解析

  这里最大的困难就是得去了解excel解析的各种api,操作excel的方式等。还得自己去摸轮子。

遇到的困难

      看了上面的选型,肯定很多人第一反应就是使用阿里的框架,靠谱,性能又好。没错我一开始也是这么决定的,但是接着就有了另外一个问题,阿里提供的easyExcel工具类不支持解析csv格式的文件解析。很不凑巧的是easypoi他支持,(正可谓鱼和熊掌不可兼得);那这时候肯定就有人说了,解析xlsx的时候用阿里的,csv用easypoi的不久ok了么?后来实操的时候依赖冲突严重,两则都引入了apache的excel解析模块...而且在单元测试的时候,发现easyExcel(阿里)的也渐渐不能满足我的“野心”了。(解析一个7.8M的xlsx文件,纯处理行读取(不做任何解析操作),2.1w行数据,耗时3.2s)

升级的思路

一、大胆的创想

    会不会是因为Java语言天生的特性,根本就发挥性能达不到极致呢?顿时脑光一乍!C语言解析excel!!!
然后想着用java通过调用jni的方式去获取文件的解析值!!!于是乎,我就在网上查各种C语言解析excel的例子,能跑通就可以做一个直接的对比。然后我东找西找,发现
一篇颇为神奇的文章:链接: [link](https://blog.csdn.net/skv00d00/article/details/123419791) ,于是乎
奇怪的只是增加了——这篇文章是解压xlsx格式的文件,然后根据里面的xml文件去做数据解析,然后一步步进入文件探究
(这里一定要注意,仅适用于xlsx格式的文档)

    好家伙,原来他就是一个压缩包文件,剩下的就是怎么从解析好的文件里面去拿到自己想要的数据信息了。经过一番简单的摸索,终于定位到了两个文件:分别是 xl/sharedStrings.xml 和 xl/worksheets/sheet1.xml 这两个文件, 第一个文件一看名字就很有来头,共享字符串?后面经过验证,发现,所有表格里面的字符数据,全部都可以在这个文件里面找得到,剩下的谜题就在sheet1.xml 文件中了,不出意外的话,肯定是利用的数据索引的方式去进行字符串关联。结果果然不出我的意料!

sheet.xml 中 row标签代表的是行信息,c标签代表是新的一列,指的是column,c标签中有两个属性,第一个属性代表他属于第几列 例如:A1、BA1列这种(BA1代表BA列,第1行),还有一个s值,这个s就标识着他是不是字符串,如果是,则需要从共享字符串文件中的索引下标去获取目标值,否则他可能是数字类型,直接读取。

二、深度解析实践

第一步

 先创建一个解析Excel的工具类(DeepExcelParse.class) ,如果只需要excel文件File对象,NodeList是用作于接收sharedStrings的管理,继承的DefaultHnadler主要是用作于sheet.xml文件的sax模式读取
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.core.util.ZipUtil;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.helpers.DefaultHandler;import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;public class DeepExcelParse extends DefaultHandler implements Closeable {private final File tempFile;private final List<Entity> result;/*** stringSharing*/private final NodeList nodeList;public DeepExcelParse(File excelFile) {tempFile = new File(excelFile.getParent(), IdUtil.fastSimpleUUID());ZipUtil.unzip(excelFile, tempFile);Document document = XmlUtil.readXML(new File(tempFile, "xl" + File.separator + "sharedStrings.xml"));this.nodeList = document.getElementsByTagName("t");this.result = new LinkedList<>();}@Overridepublic void close() throws IOException {FileUtil.del(tempFile);}}

利用到的实体对象,这里仅做DEMO展示:

    @Dataprivate class Entity{private String id;private String name;}

第二步

重写Handler解析的方法,暴露一个start开始解析的入口
 public void start(){File target = new File(tempFile, "xl" + File.separator + "worksheets" + File.separator + "sheet1.xml");if (!FileUtil.exist(target)) {throw new RuntimeException("系统异常");}XmlUtil.readBySax(target, this);}

第三步

接下来就得处理真正的解析流程了,重写DefaultHandler的方法,核心的有:startElement,endElement,characters方法
这里就不具体展示解析流程(如果有需要的话,后续再更新这里的内容),
startElement 标签开始时会调用的方法,这里可以获取到标签类型 例如:<div id='id1'><span attr='abc'>test</span></div>,他会进
入两次这个方法,一次拿到的是div标签,第二次会来到span标签,都是指的是解析开始,这里只能够获取得到id和attr属性的值,
拿不到 span标签里面的 ‘test’值
endElement方法:标签结束的回调,这里也会进入两次,刚好和上面的函数以一对对的方式进行回调
characters 方法: 这里是负责获取span标签内部的内容,方法定义:characters(char[] ch, int start, int length)
如果是字符串的话,则直接通过 new String(ch,start,length);就可以解析到标签内部的内容块。

性能测试

    捣腾了大半天之后,终于要迎来了我的性能测试对比时间了,也是同样的excel文档,2.1W行数据,解析耗时2.3秒!小点:优化的点不单止是解析方式不一样,而且我在解析文件的过程中,会跳过很多我不关心的数据列,但是现成的框架并不会知道调用者需要的是哪些字段,会逐个字段或者通过反射获取@Excel注解上面的值去决定获取哪些列的数据,但是反射终究会有性能问题。目前优化暂告一段落。

性能提升空间

上面展示的例子还是有缺点的,最大的确定就是会直接加载整个共享字符串的内容进来,在某种情况下,他可能会很大,
进而占用了大部分的内存空间,再高并发的背景下,会频繁触发GC,并且会有OOM的风险,这时候就需要更加合适的GC
处理器了,再者就是将JDK的版本升至9或以上,java9中有个新特性是专门针对String.class做出优化,核心是减少了
一些单字节可以展示的字符串的占用空间(会有两种模式,一种是jdk8以前的,用两个字节代表一个字符,现在会考虑
动态切换占用一个字节/两个字节)

小结

在经历了这一波探索之后感觉收货良多,一是把xlsx的老底掀开了解了一遍,有发现新天地的小惊喜,有性能优化上面的提升的喜悦。由最开始的12秒,优化成6秒,到最后的2.8秒!还是有相当的大的收货的。
如果有更好的解析方式也欢迎来分享!

Excel文件的深度解析相关推荐

  1. 利用js-xlsx.js插件实现Excel文件导入并解析Excel数据成json数据格式

    <!--本文转载于网络,有太多一样的文章,不知道原作者是哪位了,就不注明出处了.这里记载下来,用于自己的学习借鉴--><!DOCTYPE html><html lang= ...

  2. 使用Java泛型和反射机制编写Excel文件生成和解析的通用工具类

    前几天被派到一个小项目中做临时维护,工作地点不方便且不说,项目代码那叫一个恶心... 代码几乎完全没有注释.这应该是我们天朝大部分程序员的习惯,代码不写注释,给后面维护的同事带来多大麻烦啊! 几百行的 ...

  3. JAVA编码(27)——执行批量导入Excel文件并进行解析

    1.建立web工程引入jar包:commons-fileupload.jarcommons-lang-1.0.1.jarjspsmartupload.jarpoi-2.5-final-20040302 ...

  4. vue3采用xlsx库实现上传excel文件,前端解析展示数据(日期转换问题解决)

    项目中需要实现点击导入excel文件后前端进行解析,将数据展示在页面上,确认后上传至后台的功能,为了便于用户查看,可将所有已上传至后台的数据重新展示在页面表格中.具体实现步骤如下: 1.下载插件 np ...

  5. Excel文件写入和解析

    一.概述 使用Excel文件来进行数据的导入或导出. 二.Apache POI Apache POI 是用Java编写的免费开源的跨平台的Java API,Apache POI 提供给Java程序对M ...

  6. excel文件存入mysql_解析excel文件并将数据导入到数据库中

    今天领导给安排了一个临时工作,让我将一个excel里面的数据解析后放入数据库中,经过一个下午的努力成功完成,现在将代码献上,希望对大家有所帮助 一.需要导入的jar 1.commons-collect ...

  7. js接收excel文件流并解析下载文件

    情景:后端为post请求,且接口返回为excel文件流 方法: 1.使用原生XMLHttpRequest 2.使用原生fetch 3.使用axios import qs from 'qs'import ...

  8. HTML上传excel文件,php解析逐条打印输出

    微信小程序开发交流qq群   173683895    承接微信小程序开发.扫码加微信. 正文: phpExcel文件下载  ←跳转地址 demo <!DOCTYPE html> < ...

  9. C语言 文件操作 深度解析 #重点知识:文件操作函数的使用#

    文章目录 前言 1. 为什么使用文件 2. 什么是文件 程序文件 数据文件 3. 文件的打开和关闭 4. 文件的顺序读写 `fgetc` `fputc` `fgets` `fputs` `fprint ...

最新文章

  1. NET_NET深入体验与实战 第一章 .NET你知道 1.1什么是 .NET
  2. Django定义全局变量
  3. python对象的 init 和 del 方法
  4. java魂斗罗_java 魂斗罗
  5. Ant Design Pro入门之简介
  6. 《普林斯顿微积分读本》笔记-第1章函数、图像和直线
  7. win7自带的xps viewer很好用
  8. 【树形DP】保镖排队
  9. 人工智能研究中心快递柜——代码分析六
  10. 【微信小程序】文章点赞功能的实现
  11. python批量将excel转成pdf_Python:将PDF转成Excel
  12. 网络通信原理与IP地址的分配原理,网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层
  13. 沪漂大专程序员,一边跟刘畊宏健身,一边拿22k的offer
  14. 【2022最新】手把手教你拥有自己的服务器与网站(无需备案)
  15. SpringBoot整合Thymeleaf+EasyExcel实现excel文件的读取并展示,附加swagger2配置(超详细示范!)
  16. Window10 应用商店闪退问题
  17. 手机变速齿轮_变速齿轮手机版下载-变速齿轮 安卓版v1.0-PC6安卓网
  18. USB转4串口模块CP2108
  19. 苹果cmsV10仿B站风模板源码
  20. 持欠条讨薪无须先劳动仲裁

热门文章

  1. 计算机学院运动会宣传语,运动会宣传语(精选70条)
  2. Creator新玩法!不要错过
  3. 我的Unity(11)一点一滴 制作LOL小地图
  4. 关于升级后的_UpgradeReport_Files和Backup文件夹
  5. 【CodeForces 1042B --- Vitamins】DP+位运算
  6. Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve com xxx
  7. Python 学习笔记 列表 排序 xxx XXX
  8. 游戏策划学习第二十八天
  9. 三国志战略版:北定中原_个性系统_多视角分析
  10. 驱动SG90舵机运算