当前位置: 首页 > wzjs >正文

变更icp备案网站信息汉源网站建设

变更icp备案网站信息,汉源网站建设,二建报考条件,太原网站开发定制简介 官网地址 GitHub地址 基于MIT协议 发展历史 由EasyExcel发展而来 2018/02/07:发布1.0.0 2019/09/17:发布2.0.0 2021/10/21:发布3.0.1 2024/06/18:发布4.0.0 2024/11/06:进入维护模式 2024/12/05:发…

简介

官网地址
GitHub地址
基于MIT协议

发展历史

由EasyExcel发展而来
2018/02/07:发布1.0.0
2019/09/17:发布2.0.0
2021/10/21:发布3.0.1
2024/06/18:发布4.0.0
2024/11/06:进入维护模式
2024/12/05:发布FastExcel1.0.0

主要特性

  • 高性能读写
  • 简单易用
  • 流式操作
  • 读取执行行数

技术原理

  • 内存优化:基于流式读取技术,不需要一次性将整个Excel文件加载到内存中,逐行或逐块读取数据。
  • 事件驱动模型:基于实现ReadListener接口处理读取操作。当读取到数据时,会触发接口中的方法,如invoke方法,支持开发者对每行数据进行即时处理。
  • 注解映射:用注解将Excel文件中的列与Java对象的属性进行映射。开发者能轻松地将Excel数据转换为Java对象,同时也支持反方向操作,将Java对象写入Excel

横向对比

jxlpoifastExcel
性能对比效率低细致和完整的操作支持,OOM的问题流式处理机制,仅逐行读写数据,极大地减少了内存消耗
API 易用性纯javaAPI,对中文支持非常好,操作简单较为底层和繁琐事件驱动模型,支持自定义注解进行数据映射
灵活性与扩展性格式只支持老版本报表能够应对各种定制化需求主要针对常规的读写场景进行了优化

源码解析

设计理念

  • API友好
  • 业务扩展性
  • 内存使用率

设计模式

  • 建造者模式
    • ExcelWriterBuilder
    • ExcelWriterSheetBuilder
    • ExcelWriterTableBuilder
    • ExcelReaderSheetBuilder
  • 观察者模式
    • ReadListener
    • AnalysisEventListener
  • 责任链设计模式
    • WorkbookHandlerExecutionChain
    • SheetHandlerExecutionChain
    • RowHandlerExecutionChain
    • CellHandlerExecutionChain
  • 桥接模式
    • ExcelAnalyser
    • ExcelReadExecutor
  • 工厂模式
    • FastExcelFactory
  • 模板模式
    • CellWriteHandler
    • RowTagHandler
    • CellTagHandler
    • BlankRecordHandler

Read Excel源码解析

// 代码示例
FastExcel.read(new File(fileNameTotal), BaseEntity.class, new UploadDataListener()).sheet().doRead();

Read Excel 初始化

// 运用门面模式,降低使用者的难度,有利于框架的传播
public class FastExcel extends FastExcelFactory {}
// 所有的read()方法都会返回ExcelReaderBuilder
public static ExcelReaderBuilder read(String pathName, Class head, ReadListener readListener) {ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder();excelReaderBuilder.file(pathName);if (head != null) {excelReaderBuilder.head(head);}if (readListener != null) {excelReaderBuilder.registerReadListener(readListener);}return excelReaderBuilder;}
// 所有的sheet()方法都会到这里
// 其中new ExcelReaderSheetBuilder(build())的build()方法会执行前置的初始化操作
public ExcelReaderSheetBuilder sheet(Integer sheetNo, String sheetName) {ExcelReaderSheetBuilder excelReaderSheetBuilder = new ExcelReaderSheetBuilder(build());if (sheetNo != null) {excelReaderSheetBuilder.sheetNo(sheetNo);}if (sheetName != null) {excelReaderSheetBuilder.sheetName(sheetName);}return excelReaderSheetBuilder;}
// 到这里会根据文件类型来进行解析
private void choiceExcelExecutor(ReadWorkbook readWorkbook) throws Exception {
.....//  如果是xlsx格式,会进到这里case XLSX:XlsxReadContext xlsxReadContext = new DefaultXlsxReadContext(readWorkbook, ExcelTypeEnum.XLSX);analysisContext = xlsxReadContext;excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, null);break;.....
}
// 会到这个构造方法里 执行readOpcPackage()方法  
// 此方法内会调用poi的OPCPackage包来打开excel文件获取文件内每个sheet的数据,包括comment和hyperlink,方便后续进行处理,至此初始化部分已完成public XlsxSaxAnalyser(XlsxReadContext xlsxReadContext, InputStream decryptedStream) throws Exception {this.xlsxReadContext = xlsxReadContext;XlsxReadWorkbookHolder xlsxReadWorkbookHolder = xlsxReadContext.xlsxReadWorkbookHolder();OPCPackage pkg = readOpcPackage(xlsxReadWorkbookHolder, decryptedStream);
.....
}

Read Excel 解析

回到前面sheet()方法,会返回ExcelReaderSheetBuilder
然后调用ExcelReaderSheetBuilder里的doRead()方法

    public void doRead() {if (excelReader == null) {throw new ExcelGenerateException("Must use 'FastExcelFactory.read().sheet()' to call this method");}excelReader.read(build());excelReader.finish();}// 最后会调用初始化生成的执行器public void analysis(List<ReadSheet> readSheetList, Boolean readAll) {try {if (!readAll && CollectionUtils.isEmpty(readSheetList)) {throw new IllegalArgumentException("Specify at least one read sheet.");}analysisContext.readWorkbookHolder().setParameterSheetDataList(readSheetList);analysisContext.readWorkbookHolder().setReadAll(readAll);try {excelReadExecutor.execute();.....            }
    public void execute() {for (ReadSheet readSheet : sheetList) {readSheet = SheetUtils.match(readSheet, xlsxReadContext);if (readSheet != null) {try {xlsxReadContext.currentSheet(readSheet);// 这里传入分页数据以及处理handlerparseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(xlsxReadContext));readComments(readSheet);} catch (ExcelAnalysisStopSheetException e) {if (log.isDebugEnabled()) {log.debug("Custom stop!", e);}}xlsxReadContext.analysisEventProcessor().endSheet(xlsxReadContext);}}}
// 这边会去调用SAX解析,解析时会执行xmlReader.setContentHandler(handler)里的方法
// SAX 解析。SAX 每次解析只在内存中加载 XML 文件的一小部分,即使针对较大的 XML 文件,它也不需要占用太多的内存,也不会存在内存溢出的问题。
// 优点: 1.采用事件驱动模式一段一段的来解析数据,占用内存小 2.只在读取数据时检查数据,不需要保存在内存中 3.效率和性能较高,能解析大于系统内存的文档当然 
// 缺点: 1.与 DOM 解析器相比,使用 SAX 解析器读取 XML 文件时,解析逻辑比较复杂 2.同时无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持 XPathprivate void parseXmlSource(InputStream inputStream, ContentHandler handler) {InputSource inputSource = new InputSource(inputStream);try {SAXParserFactory saxFactory;String xlsxSAXParserFactoryName = xlsxReadContext.xlsxReadWorkbookHolder().getSaxParserFactoryName();if (StringUtils.isEmpty(xlsxSAXParserFactoryName)) {saxFactory = SAXParserFactory.newInstance();} else {saxFactory = SAXParserFactory.newInstance(xlsxSAXParserFactoryName, null);}try {saxFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);} catch (Throwable ignore) {}try {saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);} catch (Throwable ignore) {}try {saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);} catch (Throwable ignore) {}SAXParser saxParser = saxFactory.newSAXParser();XMLReader xmlReader = saxParser.getXMLReader();xmlReader.setContentHandler(handler);xmlReader.parse(inputSource);inputStream.close();} catch (IOException | ParserConfigurationException | SAXException e) {throw new ExcelAnalysisException(e);} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {throw new ExcelAnalysisException("Can not close 'inputStream'!");}}}}

我们查看传入的Handler,查看RowTagHandler,继承了AbstractXlsxTagHandler

// 会在操作前后执行动作@Overridepublic void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {}@Overridepublic void endElement(XlsxReadContext xlsxReadContext, String name) {......// 在这里调用了endRow()方法xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);......}
	// 会在dealData()方法里处理数据@Overridepublic void endRow(AnalysisContext analysisContext) {if (RowTypeEnum.EMPTY.equals(analysisContext.readRowHolder().getRowType())) {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Empty row!");}if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) {return;}}dealData(analysisContext);}
    private void dealData(AnalysisContext analysisContext) {ReadRowHolder readRowHolder = analysisContext.readRowHolder();Map<Integer, ReadCellData<?>> cellDataMap = (Map)readRowHolder.getCellMap();readRowHolder.setCurrentRowAnalysisResult(cellDataMap);int rowIndex = readRowHolder.getRowIndex();int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();boolean isData = rowIndex >= currentHeadRowNumber;if (!isData && currentHeadRowNumber == rowIndex + 1) {buildHead(analysisContext, cellDataMap);}// 到这边就会回调监听器生成对象并且到我们自定义的监听器处理数据for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {try {if (isData) {readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);} else {readListener.invokeHead(cellDataMap, analysisContext);}} catch (Exception e) {onException(analysisContext, e);break;}if (!readListener.hasNext(analysisContext)) {throw new ExcelAnalysisStopException();}}}

点击invoke()到ModelBuildEventListener生成对象监听器里,查看buildUserModel()方法,可以看到此方法在ReadSheetHolder(注解)获取对象信息,通过反射创建对象,然后对各个属性进行赋值,只会在处理到这行数据的时候封装成对应的java对象。
这也就是为什么fastexcel占用内存少的原因

    private Object buildUserModel(Map<Integer, ReadCellData<?>> cellDataMap, ReadSheetHolder readSheetHolder,AnalysisContext context) {ExcelReadHeadProperty excelReadHeadProperty = readSheetHolder.excelReadHeadProperty();Object resultModel;try {resultModel = excelReadHeadProperty.getHeadClazz().newInstance();} catch (Exception e) {throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0,new ReadCellData<>(CellDataTypeEnum.EMPTY), null,"Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e);}Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap();BeanMap dataMap = BeanMapUtils.create(resultModel);for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {Integer index = entry.getKey();Head head = entry.getValue();String fieldName = head.getFieldName();if (!cellDataMap.containsKey(index)) {continue;}ReadCellData<?> cellData = cellDataMap.get(index);Object value = ConverterUtils.convertToJavaObject(cellData, head.getField(),ClassUtils.declaredExcelContentProperty(dataMap, readSheetHolder.excelReadHeadProperty().getHeadClazz(),fieldName, readSheetHolder), readSheetHolder.converterMap(), context,context.readRowHolder().getRowIndex(), index);if (value != null) {dataMap.put(fieldName, value);}}return resultModel;}

文章转载自:

http://1rOs4GUJ.smwLr.cn
http://liLXsV0V.smwLr.cn
http://OJsynzQA.smwLr.cn
http://7QvAxIZf.smwLr.cn
http://tibsPbMv.smwLr.cn
http://uaoN651G.smwLr.cn
http://IBUH0Epg.smwLr.cn
http://N4mVDcyy.smwLr.cn
http://5nvibh4q.smwLr.cn
http://S3hPR3cq.smwLr.cn
http://YTrVuWnp.smwLr.cn
http://Outj4VHC.smwLr.cn
http://Fih2hve5.smwLr.cn
http://46QV4dqD.smwLr.cn
http://UeztVs5c.smwLr.cn
http://qCALJQMl.smwLr.cn
http://UoBysp9L.smwLr.cn
http://5f98rWbD.smwLr.cn
http://2tsbu55A.smwLr.cn
http://gP6Gz618.smwLr.cn
http://7pNb5gq9.smwLr.cn
http://wnUwGuk5.smwLr.cn
http://oNXf19RA.smwLr.cn
http://FSrKwX0N.smwLr.cn
http://vAN7sXVx.smwLr.cn
http://6HqHsCIR.smwLr.cn
http://XXFBu0Ys.smwLr.cn
http://XoPLNcat.smwLr.cn
http://miw0o3JG.smwLr.cn
http://KHLv0ha5.smwLr.cn
http://www.dtcms.com/wzjs/665849.html

相关文章:

  • dede网站如何换源码wordpress 加载 蛮
  • 邯郸网站优化怎么用手机网站建设找哪家好
  • 重庆最便宜的网站建设公司上海工程建设信息网站
  • 全国房地产网站中国建设协会八大员
  • 网站备案幕布要求营销型网站设计制作
  • 加强网站信息内容建设的意见网站热度查询
  • 怎么销售网站平凉市崆峒区建设局网站
  • 深圳网站营销seo多少费用软文广告案例分析
  • 上海做软件河源seo排名
  • 烟台H5网站设计公司生活中的网络营销有哪些
  • 12306建网站多少钱企业网站的基本功能有哪些
  • 二级建造师最好的网站wordpress纯静态网站
  • 福田专业网站建设公司wordpress漏洞复现
  • 河北建站科技网络公司wordpress 打不开页面
  • 中山网站建设价位国外wordpress主题优化
  • 网站网页制作企江宁外贸网站建设
  • 华亭县建设局网站2017专业别墅装修设计公司
  • 做国外网站建设wordpress theme for free green
  • 安卓门户网站开发wordpress 很卡
  • 多语言网站开发设计速加网零件加工网
  • 南昌p2p网站专业建设校园网站建设教程
  • 如何入侵网站后台密码建设专业网站的利弊
  • 做网站需要空间可以进入任何网站的浏览器
  • 企业做网站需要多少钱wordpress极慢
  • 帮忙做宴会的网站辽宁东方建设工程有限公司网站
  • 装饰行业模板网站网站建设个人接单
  • 基层建设网站是不是停办了wordpress做微信推广
  • 代网站备案费用吗wordpress建站多少钱
  • 没有网站可以做的广告联盟哪里找网站建设的兼职
  • dw个人网站制作模板如何仿制wordpress主题