【源码解析】EasyExcel导入导出源码解析

news2024/11/20 18:23:01

EasyExcel介绍

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。
easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便

网站

  • 官方网站:https://easyexcel.opensource.alibaba.com/
  • github地址:https://github.com/alibaba/easyexcel
  • gitee地址:https://gitee.com/easyexcel/easyexcel

数据导入

demo

    @PostMapping(value = "/t3", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public void t3(@RequestPart("file") MultipartFile file) throws IOException {
        ReadListener<OrderExcel> readListener = new ReadListener<OrderExcel>() {
            @Override
            public void invoke(OrderExcel orderExcel, AnalysisContext analysisContext) {
                System.out.println(orderExcel);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                System.out.println(analysisContext);
            }
        };
        EasyExcel.read(file.getInputStream(), OrderExcel.class, readListener).sheet().doRead();

    }
}

源码解读

EasyExcelFactory#read(InputStream, Class, ReadListener)

    public static ExcelReaderBuilder read(InputStream inputStream, Class head, ReadListener readListener) {
        ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder();
        excelReaderBuilder.file(inputStream);
        if (head != null) {
            excelReaderBuilder.head(head);
        }

        if (readListener != null) {
            excelReaderBuilder.registerReadListener(readListener);
        }

        return excelReaderBuilder;
    }

ExcelReaderBuilder#sheet(),设置sheet。

    public ExcelReaderSheetBuilder sheet() {
        return this.sheet((Integer)null, (String)null);
    }

ExcelReaderSheetBuilder#doRead,执行读取操作。

    public void doRead() {
        if (this.excelReader == null) {
            throw new ExcelGenerateException("Must use 'EasyExcelFactory.read().sheet()' to call this method");
        } else {
            this.excelReader.read(new ReadSheet[]{this.build()});
            this.excelReader.finish();
        }
    }

ExcelReader#read(ReadSheet...),读取。

    public ExcelReader read(ReadSheet... readSheet) {
        return this.read(Arrays.asList(readSheet));
    }

    public ExcelReader read(List<ReadSheet> readSheetList) {
        this.excelAnalyser.analysis(readSheetList, Boolean.FALSE);
        return this;
    }

ExcelAnalyserImpl#analysis,调用 this.excelReadExecutor.execute();

    public void analysis(List<ReadSheet> readSheetList, Boolean readAll) {
        try {
            if (!readAll && CollectionUtils.isEmpty(readSheetList)) {
                throw new IllegalArgumentException("Specify at least one read sheet.");
            } else {
                this.analysisContext.readWorkbookHolder().setParameterSheetDataList(readSheetList);
                this.analysisContext.readWorkbookHolder().setReadAll(readAll);

                try {
                    this.excelReadExecutor.execute();
                } catch (ExcelAnalysisStopException var4) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Custom stop!");
                    }
                }

            }
        } catch (RuntimeException var5) {
            this.finish();
            throw var5;
        } catch (Throwable var6) {
            this.finish();
            throw new ExcelAnalysisException(var6);
        }
    }

DefaultAnalysisEventProcessor#endRow,挨个调用监听器来处理数据。如果未设置ReadListener,那么监听器集合中只有ModelBuildEventListener

    @Override
    public 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;

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

ModelBuildEventListener#invokeModelBuildEventListener模型构建事件监听器用来构建模型。buildUserModel主要是获取传入的类信息,进行实例化。将实体类转化为Map,BeanMap dataMap = BeanMapUtils.create(resultModel);

    @Override
    public void invoke(Map<Integer, ReadCellData<?>> cellDataMap, AnalysisContext context) {
        ReadSheetHolder readSheetHolder = context.readSheetHolder();
        if (HeadKindEnum.CLASS.equals(readSheetHolder.excelReadHeadProperty().getHeadKind())) {
            context.readRowHolder()
                .setCurrentRowAnalysisResult(buildUserModel(cellDataMap, readSheetHolder, context));
            return;
        }
        context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, readSheetHolder, context));
    }

    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.converterMap(), context, context.readRowHolder().getRowIndex(), index);
            if (value != null) {
                dataMap.put(fieldName, value);
            }
        }
        return resultModel;
    }

ConverterUtils#doConvertToJavaObject,获取Converter,根据属性上的转换器进行转换操作。

    private static Object doConvertToJavaObject(ReadCellData<?> cellData, Class<?> clazz,
        ExcelContentProperty contentProperty, Map<ConverterKey, Converter<?>> converterMap, AnalysisContext context,
        Integer rowIndex, Integer columnIndex) {
        Converter<?> converter = null;
        if (contentProperty != null) {
            converter = contentProperty.getConverter();
        }

        boolean canNotConverterEmpty = cellData.getType() == CellDataTypeEnum.EMPTY
            && !(converter instanceof NullableObjectConverter);
        if (canNotConverterEmpty) {
            return null;
        }

        if (converter == null) {
            converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType()));
        }
        if (converter == null) {
            throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty,
                "Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
        }

        try {
            return converter.convertToJavaData(new ReadConverterContext<>(cellData, contentProperty, context));
        } catch (Exception e) {
            throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty,
                "Convert data " + cellData + " to " + clazz + " error ", e);
        }
    }

BeanMap的使用,通过设置Map中的key,修改实体类的数据。

    public static void main(String[] args) {
        OrderExcel orderExcel = new OrderExcel();
        BeanMap beanMap = BeanMapUtils.create(orderExcel);
        beanMap.put("orderNo", "111");
        System.out.println(beanMap);
        System.out.println(orderExcel);
    }

数据导出

demo

    @PostMapping("/t4")
    public void t4(HttpServletResponse response) throws Exception {
        OrderExcel orderExcel = new OrderExcel();
        List<OrderExcel> orderExcels = Arrays.asList(orderExcel);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        //"测试":就是我们要生成文档的名称,可以改为自己的
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        EasyExcel.write(response.getOutputStream(), OrderExcel.class).sheet("模板").doWrite(orderExcels);
    }

源码解读

ExcelWriterSheetBuilder#doWrite(java.util.Collection<?>),执行写入操作

    public void doWrite(Collection<?> data) {
        if (excelWriter == null) {
            throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method");
        }
        excelWriter.write(data, build());
        excelWriter.finish();
    }

ExcelWriter#write(Collection<?>, WriteSheet),调用内置的ExcelBuilder

    public ExcelWriter write(Collection<?> data, WriteSheet writeSheet) {
        return write(data, writeSheet, null);
    }

    public ExcelWriter write(Collection<?> data, WriteSheet writeSheet, WriteTable writeTable) {
        excelBuilder.addContent(data, writeSheet, writeTable);
        return this;
    }

ExcelBuilderImpl#addContent(),创建ExcelWriteAddExecutor进行添加操作。

    @Override
    public void addContent(Collection<?> data, WriteSheet writeSheet, WriteTable writeTable) {
        try {
            context.currentSheet(writeSheet, WriteTypeEnum.ADD);
            context.currentTable(writeTable);
            if (excelWriteAddExecutor == null) {
                excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
            }
            excelWriteAddExecutor.add(data);
        } catch (RuntimeException e) {
            finishOnException();
            throw e;
        } catch (Throwable e) {
            finishOnException();
            throw new ExcelGenerateException(e);
        }
    }

ExcelWriteAddExecutor#add,添加数据到WorkBook中。

    public void add(Collection<?> data) {
        if (CollectionUtils.isEmpty(data)) {
            data = new ArrayList<>();
        }
        WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
        int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
        if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
            newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex();
        }
        // BeanMap is out of order, so use sortedAllFieldMap
        Map<Integer, Field> sortedAllFieldMap = new TreeMap<>();
        int relativeRowIndex = 0;
        for (Object oneRowData : data) {
            int lastRowIndex = relativeRowIndex + newRowIndex;
            addOneRowOfDataToExcel(oneRowData, lastRowIndex, relativeRowIndex, sortedAllFieldMap);
            relativeRowIndex++;
        }
    }

    private void addOneRowOfDataToExcel(Object oneRowData, int rowIndex, int relativeRowIndex,
        Map<Integer, Field> sortedAllFieldMap) {
        if (oneRowData == null) {
            return;
        }
        RowWriteHandlerContext rowWriteHandlerContext = WriteHandlerUtils.createRowWriteHandlerContext(writeContext,
            rowIndex, relativeRowIndex, Boolean.FALSE);
        WriteHandlerUtils.beforeRowCreate(rowWriteHandlerContext);

        Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), rowIndex);
        rowWriteHandlerContext.setRow(row);

        WriteHandlerUtils.afterRowCreate(rowWriteHandlerContext);

        if (oneRowData instanceof Collection<?>) {
            addBasicTypeToExcel(new CollectionRowData((Collection<?>)oneRowData), row, rowIndex, relativeRowIndex);
        } else if (oneRowData instanceof Map) {
            addBasicTypeToExcel(new MapRowData((Map<Integer, ?>)oneRowData), row, rowIndex, relativeRowIndex);
        } else {
            addJavaObjectToExcel(oneRowData, row, rowIndex, relativeRowIndex, sortedAllFieldMap);
        }

        WriteHandlerUtils.afterRowDispose(rowWriteHandlerContext);
    }

ExcelWriteAddExecutor#addJavaObjectToExcel,添加java实体类到Excel中国。

    private void addJavaObjectToExcel(Object oneRowData, Row row, int rowIndex, int relativeRowIndex,
        Map<Integer, Field> sortedAllFieldMap) {
        WriteHolder currentWriteHolder = writeContext.currentWriteHolder();
        BeanMap beanMap = BeanMapUtils.create(oneRowData);
        // Bean the contains of the Map Key method with poor performance,So to create a keySet here
        Set<String> beanKeySet = new HashSet<>(beanMap.keySet());
        Set<String> beanMapHandledSet = new HashSet<>();
        int maxCellIndex = -1;
        // If it's a class it needs to be cast by type
        if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) {
            Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
            for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
                int columnIndex = entry.getKey();
                Head head = entry.getValue();
                String name = head.getFieldName();
                if (!beanKeySet.contains(name)) {
                    continue;
                }

                ExcelContentProperty excelContentProperty = ClassUtils.declaredExcelContentProperty(beanMap,
                    currentWriteHolder.excelWriteHeadProperty().getHeadClazz(), name);
                CellWriteHandlerContext cellWriteHandlerContext = WriteHandlerUtils.createCellWriteHandlerContext(
                    writeContext, row, rowIndex, head, columnIndex, relativeRowIndex, Boolean.FALSE,
                    excelContentProperty);
                WriteHandlerUtils.beforeCellCreate(cellWriteHandlerContext);

                Cell cell = WorkBookUtil.createCell(row, columnIndex);
                cellWriteHandlerContext.setCell(cell);

                WriteHandlerUtils.afterCellCreate(cellWriteHandlerContext);

                cellWriteHandlerContext.setOriginalValue(beanMap.get(name));
                cellWriteHandlerContext.setOriginalFieldClass(head.getField().getType());
                converterAndSet(cellWriteHandlerContext);

                WriteHandlerUtils.afterCellDispose(cellWriteHandlerContext);

                beanMapHandledSet.add(name);
                maxCellIndex = Math.max(maxCellIndex, columnIndex);
            }
        }
        // Finish
        if (beanMapHandledSet.size() == beanMap.size()) {
            return;
        }
        maxCellIndex++;

        Map<String, Field> ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
        initSortedAllFieldMapFieldList(oneRowData.getClass(), sortedAllFieldMap);
        for (Map.Entry<Integer, Field> entry : sortedAllFieldMap.entrySet()) {
            Field field = entry.getValue();
            String fieldName = FieldUtils.resolveCglibFieldName(field);
            boolean uselessData = !beanKeySet.contains(fieldName) || beanMapHandledSet.contains(fieldName)
                || ignoreMap.containsKey(fieldName);
            if (uselessData) {
                continue;
            }
            Object value = beanMap.get(fieldName);
            ExcelContentProperty excelContentProperty = ClassUtils.declaredExcelContentProperty(beanMap,
                currentWriteHolder.excelWriteHeadProperty().getHeadClazz(), fieldName);
            CellWriteHandlerContext cellWriteHandlerContext = WriteHandlerUtils.createCellWriteHandlerContext(
                writeContext, row, rowIndex, null, maxCellIndex, relativeRowIndex, Boolean.FALSE, excelContentProperty);
            WriteHandlerUtils.beforeCellCreate(cellWriteHandlerContext);

            // fix https://github.com/alibaba/easyexcel/issues/1870
            // If there is data, it is written to the next cell
            Cell cell = WorkBookUtil.createCell(row, maxCellIndex);
            cellWriteHandlerContext.setCell(cell);

            WriteHandlerUtils.afterCellCreate(cellWriteHandlerContext);

            cellWriteHandlerContext.setOriginalValue(value);
            cellWriteHandlerContext.setOriginalFieldClass(FieldUtils.getFieldClass(beanMap, fieldName, value));
            converterAndSet(cellWriteHandlerContext);

            WriteHandlerUtils.afterCellDispose(cellWriteHandlerContext);
            maxCellIndex++;
        }
    }

AbstractExcelWriteExecutor#doConvert,获取对应的属性上的转换器,如果获取不到,获取converterMap默认的转换器,调用转换器转换。

    private WriteCellData<?> doConvert(CellWriteHandlerContext cellWriteHandlerContext) {
        ExcelContentProperty excelContentProperty = cellWriteHandlerContext.getExcelContentProperty();

        Converter<?> converter = null;
        if (excelContentProperty != null) {
            converter = excelContentProperty.getConverter();
        }
        if (converter == null) {
            // csv is converted to string by default
            if (writeContext.writeWorkbookHolder().getExcelType() == ExcelTypeEnum.CSV) {
                cellWriteHandlerContext.setTargetCellDataType(CellDataTypeEnum.STRING);
            }
            converter = writeContext.currentWriteHolder().converterMap().get(
                ConverterKeyBuild.buildKey(cellWriteHandlerContext.getOriginalFieldClass(),
                    cellWriteHandlerContext.getTargetCellDataType()));
        }
        if (cellWriteHandlerContext.getOriginalValue() == null && !(converter instanceof NullableObjectConverter)) {
            return new WriteCellData<>(CellDataTypeEnum.EMPTY);
        }
        if (converter == null) {
            throw new ExcelWriteDataConvertException(cellWriteHandlerContext,
                "Can not find 'Converter' support class " + cellWriteHandlerContext.getOriginalFieldClass()
                    .getSimpleName() + ".");
        }
        WriteCellData<?> cellData;
        try {
            cellData = ((Converter<Object>)converter).convertToExcelData(
                new WriteConverterContext<>(cellWriteHandlerContext.getOriginalValue(), excelContentProperty,
                    writeContext));
        } catch (Exception e) {
            throw new ExcelWriteDataConvertException(cellWriteHandlerContext,
                "Convert data:" + cellWriteHandlerContext.getOriginalValue() + " error, at row:"
                    + cellWriteHandlerContext.getRowIndex(), e);
        }
        if (cellData == null || cellData.getType() == null) {
            throw new ExcelWriteDataConvertException(cellWriteHandlerContext,
                "Convert data:" + cellWriteHandlerContext.getOriginalValue()
                    + " return is null or return type is null, at row:"
                    + cellWriteHandlerContext.getRowIndex());
        }
        return cellData;
    }

在这里插入图片描述

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

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

相关文章

XPCIE1032 — 高速高精,超快交互速率的PCIe EtherCAT实时运动控制卡

产品导读 XPCIE1032是一款基于PCI Express的EtherCAT总线运动控制卡&#xff0c;可选4-16轴运动控制&#xff0c;支持多路高速数字输入输出&#xff0c;可轻松实现多轴同步控制和高速数据传输。 XPCIE1032集成了强大的运动控制功能&#xff0c;结合MotionRT7运动控制实时软核…

PyQt5桌面应用开发(17):中文书评+类结构+QWebEngineView

本文目录 PyQt5桌面应用系列PyQt5学习PyQt5类结构和帮助速查实现与解释最终界面和完整源代码界面完整的代码 总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2&#xff09;&#xff1a;事件循环 PyQt5桌…

【中危】Apache Ranger 2.3.0 存在远程代码执行漏洞

漏洞描述 Apache Ranger 是一款用于在 Hadoop 平台及其他平台启用、监控和管理全面的数据安全性的开源框架。Apache Ranger 表达式策略是一种动态访问控制策略&#xff0c;通过自定义表达式来指定更细粒度的访问控制条件。 Apache Ranger 受影响版本中具有管理员权限或策略管…

【微博-自定义Cell-创建子控件 Objective-C语言】

一、自定义Cell 1.既然我们要自定义Cell,这个自定义Cell,属于MVC哪个部分, 这个Cell类,属于MVC哪个部分, Model、Controller、还是View, View吧, 所以说,应该在这里去新建一个类, 在这里去新建一个类,右键,New File,

SpringBoot中使用枚举类、switch、常量类(声明并初始化map)实现类策略者模式,接口返回常量数据

场景 SpringBoot中策略模式工厂模式业务实例(接口传参-枚举类查询策略映射关系-执行不同策略)规避大量if-else&#xff1a; SpringBoot中策略模式工厂模式业务实例(接口传参-枚举类查询策略映射关系-执行不同策略)规避大量if-else_霸道流氓气质的博客-CSDN博客 SpringBootVa…

Python对Excel文件多表对多表之间的匹配(两种不同表头)——之json版

首先Excel文件多表对多表之间的匹配(VLOOKUP),有多种办法&#xff0c; 1&#xff1a;将Excel文件导入Mysql或其他数据库,然后将两种表合并成一张表&#xff0c;接着用数据库匹配 2&#xff1a;将两种表内容&#xff0c;复制粘贴到一起&#xff0c;各自分别保存成一张表&#xf…

伦茨科技带你了解蓝牙App开发的流程

随着移动互联网的快速发展&#xff0c;给我们的生活带来了越来越多的便利&#xff0c;蓝牙App的开发也越来越普及。那么&#xff0c;简单来说&#xff0c;蓝牙App软件的开发就是在手机上为蓝牙物理设备提供具有相关功能的App软件终端&#xff0c;让蓝牙设备更方便的为用户提供服…

appsync unified怎么安装

一、什么是AppSync Unified&#xff1f; AppSync Unified是一款iOS设备上的越狱插件&#xff0c;它可以帮助用户安装和运行未经苹果审核的应用程序和插件。AppSync Unified可以支持iOS 11-14系统&#xff0c;并可以在iPhone和iPad上使用。它的功能主要是允许用户安装和运行不经…

电脑正常开机后几分钟就黑屏一直循环怎么办?

电脑正常开机后几分钟就黑屏一直循环怎么办&#xff1f;有用户在使用电脑的时候&#xff0c;正常去进行电脑的开机&#xff0c;但是开机之后&#xff0c;却发现屏幕变成了黑屏&#xff0c;而且重新启动电脑之后&#xff0c;依然是会出现这样的问题&#xff0c;那么这个情况怎么…

mmdetection3d框架安装与Demo模型运行--基于Ubuntu18.04+Cuda10.1

1.NVIDIA Driver和Cuda安装 在Ubuntu18.04机器上安装好NVIDIA Driver4.18和CUDA10.1&#xff0c;版本号分别为4.18和10.1 查看NVIDIA Driver版本号&#xff1a;nvidia-smi 查看CUDA版本号&#xff1a;nvcc -V 2.安装MiniConda&#xff0c;并创建和管理虚拟环境 2.1 安装Min…

八、数据仓库详细介绍(监控告警)

1. 前言 在前边的章节&#xff0c;我们设计完存储模型&#xff0c;开发了 ETL 任务&#xff0c;并且配置好流程依赖&#xff0c;然后上调度系统&#xff0c;至此我们的数据仓库基本搭建完成&#xff0c;而且所有流程任务都可以自动化运转了。 随着公司上线的数据处理任务越来越…

Linux - 第17节 - 网络基础(应用层三)

1.HTTPS协议 1.1.HTTPS简介 HTTPS也是⼀个应⽤层协议&#xff0c;是在HTTP协议的基础上引⼊了⼀个加密层。 HTTP协议内容都是按照文本的方式明文传输的&#xff0c;明文传输是不安全的&#xff0c;所以现在主流的解决 方式是在http所在的应用层和tcp所在的传输层之间加一层SSL…

Windows操作系统的文件组织结构和计算方法

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天总结一下Windows操作系统的文件组织结构和计算方法。 这是一块非常实用的知识&#xff0c;感谢大家来看这个帖子。 Windows组织结构就是文件的组织形式&#xff0c;其中&#xff1a; 1.Windows逻辑结构…

HTTPS的加密流程

HTTPS的加密流程 &#x1f50e;加密&#x1f50e;HTTPS的基本工作过程使用对称加密引入非对称加密黑客的反制(中间人攻击)一山更比一山高(引入证书) &#x1f50e;结尾 &#x1f50e;加密 加密 对称加密非对称加密 对称加密&#x1f36d; 只需要一个密钥(Key) 明文 Key 密…

【Java系列】深入解析枚举类型

序言 即便平凡的日子仿佛毫无波澜&#xff0c;但在某个特定的时刻&#xff0c;执着的努力便会显现出它的价值和意义。 希望这篇文章能让你不仅有一定的收获&#xff0c;而且可以愉快的学习&#xff0c;如果有什么建议&#xff0c;都可以留言和我交流 问题 思考一下这寄个问题&a…

行为型设计模式01-策略模式

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 策略模式 问题引入&#xff1a;实现一个商场收银软件&#xff0c;简单的实现就是单价和数量的乘积。 1、商场收银软件 下面就来看…

掌握RDD分区

零、本讲学习目标 学会如何指定分区数量会定义与使用自定义分区器 一、RRD分区 &#xff08;一&#xff09;RDD分区概念 RDD是一个大的数据集合&#xff0c;该集合被划分成多个子集合分布到了不同的节点上&#xff0c;而每一个子集合就称为分区&#xff08;Partition&#…

3.5 RDD持久化机制

一、RDD持久化 1、不采用持久化操作 查看要操作的HDFS文件 以集群模式启动Spark Shell 按照图示进行操作&#xff0c;得RDD4和RDD5 查看RDD4内容&#xff0c;会从RDD1到RDD2到RDD3到RDD4跑一趟 显示RDD5内容&#xff0c;也会从RDD1到RDD2到RDD3到RDD5跑一趟 2、采用持久化…

python解析html数据,获取到的链接是以/或 ./ 或 ../ 开头的相对链接,不是以http开头的,需要补全

一、实现的目标 在使用爬虫获取网页html数据时,解析到的链接是/或./ 开头的相对链接,不是以http开头的链接,如:/picture/0/cca65350643c441e80d390ded3975db0.png 。此时需要完成对该链接的补全,以得到正确的链接。此外,我们需要将解析到的html数据保存到起来,将来需要展…

3.8 Spark RDD典型案例

一、利用RDD计算总分与平均分 &#xff08;一&#xff09;准备工作 1、启动HDFS服务 2、启动Spark服务 3、在本地创建成绩文件 4、将成绩文件上传到HDFS &#xff08;二&#xff09;完成任务 1、在Spark Shell里完成任务 &#xff08;1&#xff09;读取成绩文件&#xff…