EasyExcel的源码流程(导入Excel)

1. 入口

2.  EasyExcel类继承了EasyExcelFactory类,EasyExcel自动拥有EasyExcelFactory父类的所有方法,如read(),readSheet(),write(),writerSheet()等等。

3. 进入.read()方法,需要传入三个参数(文件路径,表头映射类,read监听器)
   首先调用new ExcelReaderBuilder()方法,初始化ReadWorkbook对象
   设置完readWorkbook属性后调,返回excelReaderBuilder对象 

4. 这里又个传入的参数是read监听器,进入其内部看一下,我们自定义了PersonListener实现了ReadListener。ReadListener接口源码 :

自定义的PersonListener类:

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.aliyun.odps.jdbc.utils.LoggerFactory;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;@Component
public class PersonListener extends AnalysisEventListener<PersonTest> {//一行一行读出excel内容  不读表头  EasyExcel之所以效率高,也是因它一行一行读取,解析。@Overridepublic void invoke(PersonTest personTest, AnalysisContext analysisContext) {System.out.println("***"+personTest);}//读取表头@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {System.out.println("表头"+headMap);}//读取完执行的方法@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {System.out.println("读取全部后执行");}
}

5. 接下来调用的是.sheet()方法,这里我们会传入sheetNo、sheetName参数,调用build()方法创建ExcelReader对象,传入ExcelReaderSheetBuilder构造方法中,最终创ExcelReaderSheetBuilder对象 

6. 进入build()方法,build()方法生成了ExcelReader对象,初始化ExcelAnalyser,并实例化ExcelAnalyser。

在实例化ExcelAnalyser时,choiceExcelExecutor()方法通过excel格式使用不同的执行器。
我们看XLSX中,初始化了XlsxReadContext上下文对象,给到analysisContext,又初始化了XlsxSaxAnalyser解析器对象 

public class ExcelAnalyserImpl implements ExcelAnalyser {private static final Logger LOGGER = LoggerFactory.getLogger(ExcelAnalyserImpl.class);private AnalysisContext analysisContext;private ExcelReadExecutor excelReadExecutor;/*** Prevent multiple shutdowns*/private boolean finished = false;public ExcelAnalyserImpl(ReadWorkbook readWorkbook) {try {choiceExcelExecutor(readWorkbook);} catch (RuntimeException e) {finish();throw e;} catch (Throwable e) {finish();throw new ExcelAnalysisException(e);}}private void choiceExcelExecutor(ReadWorkbook readWorkbook) throws Exception {ExcelTypeEnum excelType = ExcelTypeEnum.valueOf(readWorkbook);switch (excelType) {case XLS:POIFSFileSystem poifsFileSystem;if (readWorkbook.getFile() != null) {poifsFileSystem = new POIFSFileSystem(readWorkbook.getFile());} else {poifsFileSystem = new POIFSFileSystem(readWorkbook.getInputStream());}// So in encrypted excel, it looks like XLS but it's actually XLSXif (poifsFileSystem.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {InputStream decryptedStream = null;try {decryptedStream = DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), readWorkbook.getPassword());XlsxReadContext xlsxReadContext = new DefaultXlsxReadContext(readWorkbook, ExcelTypeEnum.XLSX);analysisContext = xlsxReadContext;excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, decryptedStream);return;} finally {IOUtils.closeQuietly(decryptedStream);// as we processed the full stream already, we can close the filesystem here// otherwise file handles are leakedpoifsFileSystem.close();}}if (readWorkbook.getPassword() != null) {Biff8EncryptionKey.setCurrentUserPassword(readWorkbook.getPassword());}XlsReadContext xlsReadContext = new DefaultXlsReadContext(readWorkbook, ExcelTypeEnum.XLS);xlsReadContext.xlsReadWorkbookHolder().setPoifsFileSystem(poifsFileSystem);analysisContext = xlsReadContext;excelReadExecutor = new XlsSaxAnalyser(xlsReadContext);break;case XLSX:XlsxReadContext xlsxReadContext = new DefaultXlsxReadContext(readWorkbook, ExcelTypeEnum.XLSX);analysisContext = xlsxReadContext;excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, null);break;case CSV:CsvReadContext csvReadContext = new DefaultCsvReadContext(readWorkbook, ExcelTypeEnum.CSV);analysisContext = csvReadContext;excelReadExecutor = new CsvExcelReadExecutor(csvReadContext);break;default:break;}}
/*
----------------------------------------略---------------------------------------------
*/
}

7. XlsxSaxAnalyser详解

    7.1 进入new XlsxSaxAnalyser(xlsxReadContext, null)方法看一下,这里使用到SAX模式模式解析excel

public XlsxSaxAnalyser(XlsxReadContext xlsxReadContext, InputStream decryptedStream) throws Exception {this.xlsxReadContext = xlsxReadContext;// 初始化缓存(cache)XlsxReadWorkbookHolder xlsxReadWorkbookHolder = xlsxReadContext.xlsxReadWorkbookHolder();OPCPackage pkg = readOpcPackage(xlsxReadWorkbookHolder, decryptedStream);xlsxReadWorkbookHolder.setOpcPackage(pkg);// Read the Shared information StringsPackagePart sharedStringsTablePackagePart = pkg.getPart(SHARED_STRINGS_PART_NAME);if (sharedStringsTablePackagePart != null) {// 指定默认缓存defaultReadCache(xlsxReadWorkbookHolder, sharedStringsTablePackagePart);// 分析sharedStringsTable.xml,解析excel所有数据到readCacheanalysisSharedStringsTable(sharedStringsTablePackagePart.getInputStream(), xlsxReadWorkbookHolder);}XSSFReader xssfReader = new XSSFReader(pkg);analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder);// 设置样式表setStylesTable(xlsxReadWorkbookHolder, xssfReader);sheetList = new ArrayList<>();sheetMap = new HashMap<>();commentsTableMap = new HashMap<>();Map<Integer, PackageRelationshipCollection> packageRelationshipCollectionMap = MapUtils.newHashMap();xlsxReadWorkbookHolder.setPackageRelationshipCollectionMap(packageRelationshipCollectionMap);// 获取所有sheet页XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData();int index = 0;if (!ite.hasNext()) {throw new ExcelAnalysisException("Can not find any sheet!");}// 遍历sheet页while (ite.hasNext()) {InputStream inputStream = ite.next();// 保存所有sheet页sheetList.add(new ReadSheet(index, ite.getSheetName()));// 保存所有sheet页的输入流sheetMap.put(index, inputStream);if (xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) {CommentsTable commentsTable = ite.getSheetComments();if (null != commentsTable) {commentsTableMap.put(index, commentsTable);}}if (xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.HYPERLINK)) {PackageRelationshipCollection packageRelationshipCollection = Optional.ofNullable(ite.getSheetPart()).map(packagePart -> {try {return packagePart.getRelationships();} catch (InvalidFormatException e) {log.warn("Reading the Relationship failed", e);return null;}}).orElse(null);if (packageRelationshipCollection != null) {packageRelationshipCollectionMap.put(index, packageRelationshipCollection);}}index++;}}

    7.2 进入analysisSharedStringsTable方法,可以看到创建了一个SharedStringsTableHandler处理器

    7.3 再进入parseXmlSource看到xmlReader.setContentHandler(handler)这一行代码,设置了SharedStringsTableHandler处理器

private 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'!");}}}}

    7.4 我们将断点打在SharedStringsTableHandler里,发现下一步进入到这里面的startElement()    starteElement()后会调用endElement()

    7.5 反复调用,excel所有数据读取到readcache中

8. 调用.doRead()方法,开始SAX解析

    8.1 进入build()方法

    8.2 build()执行完后,执行read()方法,read()里还会进入一次read() 

9. 调用ExcelAnalyserImpl里的analysis()方法,设置sheetList,并调用执行器开始执行解析 

    9.1 调用的XlsxSaxAnalyser解析器execute()

 10. 进入parseXmlSource()方法,发现和之前的sax差不多,但只两次传入的handler类型不同,还是看一下传入的ContentHandler参数具体实现,进入XlsxRowHandler 内部

public class XlsxRowHandler extends DefaultHandler {private final XlsxReadContext xlsxReadContext;private static final Map<String, XlsxTagHandler> XLSX_CELL_HANDLER_MAP = new HashMap<String, XlsxTagHandler>(32);static {CellFormulaTagHandler cellFormulaTagHandler = new CellFormulaTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, cellFormulaTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_FORMULA_TAG, cellFormulaTagHandler);CellInlineStringValueTagHandler cellInlineStringValueTagHandler = new CellInlineStringValueTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);CellTagHandler cellTagHandler = new CellTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, cellTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_TAG, cellTagHandler);CellValueTagHandler cellValueTagHandler = new CellValueTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, cellValueTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_VALUE_TAG, cellValueTagHandler);CountTagHandler countTagHandler = new CountTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION_TAG, countTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_DIMENSION_TAG, countTagHandler);HyperlinkTagHandler hyperlinkTagHandler = new HyperlinkTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, hyperlinkTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_HYPERLINK_TAG, hyperlinkTagHandler);MergeCellTagHandler mergeCellTagHandler = new MergeCellTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, mergeCellTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_MERGE_CELL_TAG, mergeCellTagHandler);RowTagHandler rowTagHandler = new RowTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, rowTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_ROW_TAG, rowTagHandler);}public XlsxRowHandler(XlsxReadContext xlsxReadContext) {this.xlsxReadContext = xlsxReadContext;}@Overridepublic void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name);if (handler == null || !handler.support(xlsxReadContext)) {return;}xlsxReadContext.xlsxReadSheetHolder().getTagDeque().push(name);handler.startElement(xlsxReadContext, name, attributes);}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {String currentTag = xlsxReadContext.xlsxReadSheetHolder().getTagDeque().peek();if (currentTag == null) {return;}XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(currentTag);if (handler == null || !handler.support(xlsxReadContext)) {return;}handler.characters(xlsxReadContext, ch, start, length);}@Overridepublic void endElement(String uri, String localName, String name) throws SAXException {XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name);if (handler == null || !handler.support(xlsxReadContext)) {return;}handler.endElement(xlsxReadContext, name);xlsxReadContext.xlsxReadSheetHolder().getTagDeque().pop();}}

    10.1 startElement()和endElement()都有多种实现

11. 进入用到的重要的几个类CellTagHandler、RowTagHandler

CellTagHandler: 读取cell的值,并放入tempCellData

public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();xlsxReadSheetHolder.setColumnIndex(PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),xlsxReadSheetHolder.getColumnIndex()));// t="s" ,it means String// t="str" ,it means String,but does not need to be read in the 'sharedStrings.xml'// t="inlineStr" ,it means String,but does not need to be read in the 'sharedStrings.xml'// t="b" ,it means Boolean// t="e" ,it means Error// t="n" ,it means Number// t is null ,it means Empty or NumberCellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_T));xlsxReadSheetHolder.setTempCellData(new ReadCellData<>(type));xlsxReadSheetHolder.setTempData(new StringBuilder());// Put in data transformation informationString dateFormatIndex = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_S);int dateFormatIndexInteger;if (StringUtils.isEmpty(dateFormatIndex)) {dateFormatIndexInteger = DEFAULT_FORMAT_INDEX;} else {dateFormatIndexInteger = Integer.parseInt(dateFormatIndex);}xlsxReadSheetHolder.getTempCellData().setDataFormatData(xlsxReadContext.xlsxReadWorkbookHolder().dataFormatData(dateFormatIndexInteger));}@Overridepublic void endElement(XlsxReadContext xlsxReadContext, String name) {XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();ReadCellData<?> tempCellData = xlsxReadSheetHolder.getTempCellData();StringBuilder tempData = xlsxReadSheetHolder.getTempData();String tempDataString = tempData.toString();CellDataTypeEnum oldType = tempCellData.getType();switch (oldType) {case STRING:// In some cases, although cell type is a string, it may be an empty tagif (StringUtils.isEmpty(tempDataString)) {break;}String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache().get(Integer.valueOf(tempDataString));tempCellData.setStringValue(stringValue);break;case DIRECT_STRING:case ERROR:tempCellData.setStringValue(tempDataString);tempCellData.setType(CellDataTypeEnum.STRING);break;case BOOLEAN:if (StringUtils.isEmpty(tempDataString)) {tempCellData.setType(CellDataTypeEnum.EMPTY);break;}tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString()));break;case NUMBER:case EMPTY:if (StringUtils.isEmpty(tempDataString)) {tempCellData.setType(CellDataTypeEnum.EMPTY);break;}tempCellData.setType(CellDataTypeEnum.NUMBER);tempCellData.setNumberValue(BigDecimal.valueOf(Double.parseDouble(tempDataString)));break;default:throw new IllegalStateException("Cannot set values now");}if (tempCellData.getStringValue() != null&& xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {tempCellData.setStringValue(tempCellData.getStringValue().trim());}tempCellData.checkEmpty();tempCellData.setRowIndex(xlsxReadSheetHolder.getRowIndex());tempCellData.setColumnIndex(xlsxReadSheetHolder.getColumnIndex());xlsxReadSheetHolder.getCellMap().put(xlsxReadSheetHolder.getColumnIndex(), tempCellData);}

RowTagHandler: 当一行读取完毕后,调用分析事件处理器,处理一行数据

                            xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);

public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),xlsxReadSheetHolder.getRowIndex());Integer lastRowIndex = xlsxReadContext.readSheetHolder().getRowIndex();while (lastRowIndex + 1 < rowIndex) {xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap<Integer, Cell>()));xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);xlsxReadSheetHolder.setColumnIndex(null);xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());lastRowIndex++;}xlsxReadSheetHolder.setRowIndex(rowIndex);}@Overridepublic void endElement(XlsxReadContext xlsxReadContext, String name) {XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;// It's possible that all of the cells in the row are emptyif (rowType == RowTypeEnum.DATA) {boolean hasData = false;for (Cell cell : xlsxReadSheetHolder.getCellMap().values()) {if (!(cell instanceof ReadCellData)) {hasData = true;break;}ReadCellData<?> readCellData = (ReadCellData<?>)cell;if (readCellData.getType() != CellDataTypeEnum.EMPTY) {hasData = true;break;}}if (!hasData) {rowType = RowTypeEnum.EMPTY;}}xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);xlsxReadSheetHolder.setColumnIndex(null);xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());}

12. 进入endRow()方法

      endRow()里通过getIgnoreEmptyRow()来判断是否忽略空行(true为忽略,默认为true)

     想要设置IgnoreEmptyRow为false,可以在最初使用EasyExcel时设置:

13. 进入dealData()方法

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;// Last head columnif (!isData && currentHeadRowNumber == rowIndex + 1) {buildHead(analysisContext, cellDataMap);}// Now is datafor (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();}}}

14. dealData()方法中的invoke方法会执行ModelBuildEventListener里的invoke()方法,在这里会进行单行数据到实体类的映射,buildStringList()真正执行映射

15. 退回XlsxSaxAnalyser的解析器execute()方法

      进入readComments()方法,读取额外信息(批注、超链接、合并单元格信息读取)

	private void readComments(ReadSheet readSheet) {if (!xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) {return;}CommentsTable commentsTable = commentsTableMap.get(readSheet.getSheetNo());if (commentsTable == null) {return;}Iterator<CellAddress> cellAddresses = commentsTable.getCellAddresses();while (cellAddresses.hasNext()) {CellAddress cellAddress = cellAddresses.next();XSSFComment cellComment = commentsTable.findCellComment(cellAddress);CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.COMMENT, cellComment.getString().toString(),cellAddress.getRow(), cellAddress.getColumn());xlsxReadContext.readSheetHolder().setCellExtra(cellExtra);xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext);}}

16. 最后进入.endSheet(xlsxReadContext)方法

@Overridepublic void endSheet(AnalysisContext analysisContext) {// 这里会调用所有监听器中的doAfterAllAnalysed方法,执行最后的操作for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {readListener.doAfterAllAnalysed(analysisContext);}}

17. 在读取完毕之后,执行finish()方法,关闭所有流 

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

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

相关文章

【C++】:类和对象(1)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关C中类和对象的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通…

Windows电脑显示部分功能被组织控制

目录 问题描述 解决方法 总结 问题描述 如果你的电脑出现以上情况&#xff0c;建议你使用我这种方法&#xff08;万不得已&#xff09; 解决方法 原因就是因为当时你的电脑在激活的时候是选择了组织性激活的&#xff0c;所以才会不管怎么搞&#xff0c;都无法摆脱组织的控…

十五、异常(4)

本章概要 Java 标志异常 特例&#xff1a;RuntimeException 使用 finally 进行清理 finally 用来做什么&#xff1f;在 return 中使用 finally缺憾&#xff1a;异常丢失 Java 标准异常 Throwable 这个 Java 类被用来表示任何可以作为异常被抛出的类。Throwable 对象可分为两…

ubuntu下源码编译方式安装opencv

基础条件 ubuntu 20.04 opencv 3.4.3 opencv 源码编译的安装步骤 第一步&#xff0c; 首先clone源码 git clone https://github.com/opencv/opencv.git第二步&#xff0c;依赖包&#xff0c;执行下面的命令 sudo apt-get install build-essential sudo apt-get install cmak…

Android studio “Layout Inspector“工具在Android14 userdebug设备无法正常使用

背景描述 做rom开发的都知道&#xff0c;“Layout Inspector”和“Attach Debugger to Android Process”是studio里很好用的工具&#xff0c;可以用来查看布局、调试系统进程&#xff08;比如setting、launcher、systemui&#xff09;。 问题描述 最进刚开始一个Android 14…

Android Shape设置背景

设置背景时&#xff0c;经常这样 android:background“drawable/xxx” 。如果是纯色图片&#xff0c;可以考虑用 shape 替代。 shape 相比图片&#xff0c;减少资源占用&#xff0c;缩减APK体积。 开始使用。 <?xml version"1.0" encoding"utf-8"?…

云安全之HTTP协议介绍

HTTP的基本概念 什么是网络协议 网络协议是计算机之间为了实现网络通信而达成的一种“约定”或者”规则“&#xff0c;有了这种”约定不同厂商生产的设备&#xff0c;以及不同操作系统组成的计算机之间&#xff0c;就可以实现通信。 网络协议由三个要素构成&#xff1a;1、语…

WSL2和ubuntu的安装过程

目录 1.WSL2的安装 2.Ubuntu的安装 3.安装完成后的打开方式 1.WSL2的安装 按下WINX键&#xff0c;选择Windows PowerShell (管理员) 1.1执行以下命令&#xff0c;该命令的作用是&#xff1a;启用适用于 Linux 的 Windows 子系统 dism.exe /online /enable-feature /featur…

【小沐学前端】Node.js实现基于Protobuf协议的WebSocket通信

文章目录 1、简介1.1 Node1.2 WebSocket1.3 Protobuf 2、安装2.1 Node2.2 WebSocket2.2.1 nodejs-websocket2.2.2 ws 2.3 Protobuf 3、代码测试3.1 例子1&#xff1a;websocket&#xff08;html&#xff09;3.1.1 客户端&#xff1a;yxy_wsclient1.html3.1.2 客户端&#xff1a…

利用mAP计算yolo精确度

当将yolo算法移植部署在嵌入式设备上&#xff0c;为了验证算法的准确率。将模型测试的结果保存为txt文件&#xff08;每一个txt文件&#xff0c;对应一个图片&#xff09;。此外&#xff0c;需要将数据集中的标签由[x,y,w,h]转为[x1,y1,x2,y2]。最后&#xff0c;运行验证代码 …

Secureboot从入门到精通

关键词&#xff1a;trustzone视频、tee视频、ATF视频、secureboot视频、安全启动视频、selinux视频&#xff0c;cache视频、mmu视频&#xff0c;armv8视频、armv9视频 FF-A视频、密码学视频、RME/CCA视频、学习资料下载、免费学习资料、免费 周贺贺&#xff0c;baron&#xff0…

把握现在,热爱生活

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录 厨艺房价琐事计划随想 今年的中秋国庆假期放8天&#xff0c;比春节假期…

Centos7配置firewalld防火墙规则

这里写自定义目录标题 欢迎使用Markdown编辑器一、简单介绍二、特点和功能2.1、区域&#xff08;Zone&#xff09;2.2、运行时和永久配置2.3、服务和端口2.4、动态更新2.5、连接跟踪2.6、D-Bus接口 三、设置规则3.1、启动防火墙服务3.2、新建防火墙规则的服务&#xff0c;添加端…

分布式链路追踪--SkyWalking7.0.0+es7.0.0

分布式链路追踪–SkyWalking ​ 微服务的出现&#xff0c;的确解决了一些业务痛点&#xff0c;但是也造成了新的问题比如随着调用链的拉长&#xff0c;如果想要知道请求为什么这么慢&#xff0c;这个请求到底经历了哪些环节&#xff0c;又依赖了哪些东西&#xff0c;在微服务架…

亲测可用国产GPT人工智能

分享一些靠谱、可用、可以白嫖的GPT大模型。配合大模型&#xff0c;工作效率都会极大提升。 清华大学ChatGLM 官网&#xff1a; 智谱清言中国版对话语言模型&#xff0c;与GLM大模型进行对话。https://chatglm.cn/开源的、支持中英双语的1300亿参数的对话语言模型&#xff0…

【MATLAB】字体美化和乱码

文章目录 前言首先说说说字体美化乱码到底是怎么导致的&#xff1f;1 字体导致的乱码2 编码导致的乱码总结 前言 最近打开MATLAB&#xff0c;又发现了一个问题&#xff1a;编辑器中的中文输入在命令行或者说终端输出竟然是乱码&#xff0c;然后赶紧翻阅了一下此前的博客以及未发…

使用VBA实现快速模糊查询数据

实例需求&#xff1a;基础数据保存在Database工作表中&#xff0c;如下图所示。 基础数据有37个字段&#xff0c;上图仅展示部分字段内容&#xff0c;下图中黄色字段为需要提取的数据字段。 在Search工作表B1单元格输入查询关键字Title和Genre字段中搜索关键字&#xff0c;包…

【数据结构--八大排序】之归并排序

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Armv9 Cortex-A720的L2 memory system 和 L2 Cache

9 L2 memory system Cortex-A720核心的L2内存系统通过CPU bridge连接core与DynamIQ Shared Unit-120,其中包括私有的L2缓存。 L2缓存是统一的,每个Cortex-A720核心在一个集群中都有私有的L2缓存。 L2内存系统包括使用虚拟地址(VA)和程序计数器(PC)的数据预取引擎。不同…

【2023研电赛】华东赛区一等奖:电动叉车永磁同步电机MTPA及弱磁控制研究

本文为2023年第十八届中国研究生电子设计华东赛区一等奖竞赛作品分享&#xff0c;参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&#xff01;&#xff0c;分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&a…