Excel的技术分享

news2024/9/21 18:35:30

导出Excel的技术分享

Excel前置知识

首先大家就是在大学的计算机导论等课程肯定有了解过office全家桶中的工具之一Excel。在印象当中就是Excel是普遍使用的就是有03和07的两个不同的版本。请问一下大家就是能说一说就是这两个版本有什么区别吗?
显而易见就是从了直观上,能看到就是07的版本在文件的后缀名上多了一个x。但是除了这个之外还有什么别的不同吗?
在这里插入图片描述

可能大家也一下就想到了那就是这两者的导出的行数是存在限制的。03版本的Excel是在65536行之后存在大量的白内障。而在07版本中则明显在数据容量上进行了巨大的提升。但是也是存在上限的。白内障出现的位置是在1048576行之后。百万行的数据量相比之前的03版本已经能极大的提高我们的日常工作数据所需。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Excel的基本组成介绍

在导出一个Excel基本的组成部分在代码中体现的就是这四个骨架。

在这里插入图片描述

目前的主流导出Excel技术介绍

在阿里巴巴开源的导出Excel工具包中介绍了三个工具。EasyExcel、Apache poi、jxl。其中目前关于这三者的技术中的最后的JXL技术是是Java中的一个原生类库。但是它只能支持Excel 95-2000。比03Excel还要古老而且这个类库已经停止更新和维护了。EasyExcel、Apache poi这两个项目一直在更新,今天就和大家分享一下这两个工具在使用上的一些实现。

EasyExcel是在POI基础之上的一些封装,所以在介绍他之前我们先来介绍一下Apache poi。

在这里插入图片描述

Apache poi工具的介绍

Apache POI是用Java语言编写的工具,这一点上来不想其他的工具使用别的语言来实现(例如redis使用C/C++编写)说对Java的开发者还是比较友好的能直接看懂。Apache POI 是基于 Office Open XML 标准(OOXML)和 Microsoft 的 OLE 2 复合⽂档格式(OLE2)处理各种⽂件格式的开源项⽬。 简⽽⾔之,可以使⽤ Java 读写MS Excel ⽂件,可以使⽤ Java 读写 MS Word 和 MS PowerPoint ⽂件。

在这里插入图片描述

功能模块的介绍:

  • HSSF:提供读写 Microsoft Excel XLS 格式 (Microsoft Excel 97 (-2003)) 档案的功能。
  • XSSF:提供读写 Microsoft Excel OOXML XLSX 格式 (Microsoft Excel XML (2007+))档案的功能。
  • SXSSF:提供低内存占⽤量读写 Microsoft Excel OOXML XLSX 格式档案的功能。针对大数量的写入量身打造。
  • HWPF:提供读写 Microsoft Word DOC97 格式 (Microsoft Word 97 (-2003)) 档案的功能。
  • XWPF:提供读写 Microsoft Word DOC2003 格式 (WordprocessingML (2007+)) 档案的功能。
  • HSLF/XSLF:提供读写 Microsoft PowerPoint 格式档案的功能。
  • HDGF/XDGF:提供读 Microsoft Visio 格式档案的功能。
  • HPBF:提供读 Microsoft Publisher 格式档案的功能。
  • HSMF:提供读 Microsoft Outlook 格式档案的功能。

上面的九大功能模块有的并没有直接显示,例如SXSSF在XSSF的内部。

在这里插入图片描述

使用POI完成对一个基本的Excel的数据写入

通过前面对Excel的格式骨架的介绍,大致可以将书写Eexcel的编码实现分为六大步骤。

  1. 创建工作簿:Workbook。
  2. 创建工作表:sheet。
  3. 创建行:Row。
  4. 创建列上的单元格:Cell。
  5. 完成对数据的写入。
  6. 使用字节流完成文件的最终生成

生成03版本Excel的效果演示

由下面的65536行一下就成为了白内障区域和文件名是xls后缀证明目前生成时03版本的Excel

在这里插入图片描述

在这里插入图片描述

生成03版本Excel代码示例

  public static void GenerateExcel03() throws  Exception {
        // 创建工作簿
        Workbook workbook = new HSSFWorkbook();

        // 创建工作表
        Sheet sheet = workbook.createSheet("03版本");

        // 创建行 第0行 row0
        Row row0 = sheet.createRow(0);

        // 创建行上的单元格 第一行第一个
        Cell cell01 = row0.createCell(0);
        // 创建行上单元格 第一行第二个
        Cell cell02 = row0.createCell(1);

        // 创建行 第1行row0
        Row row1 = sheet.createRow(1);
        // 创建第二行第一个
        Cell cell11 = row1.createCell(0);
        // 创建第二行第二个
        Cell cell12 = row1.createCell(1);
        // 第二行第一个赋值
        cell11.setCellValue("小花");
        cell12.setCellValue("18");


        // 数据写入
        cell01.setCellValue("姓名");
        cell02.setCellValue("年龄");


        // 利用流生成Excel表格
        FileOutputStream fileOutputStream = new FileOutputStream("./03版本的Excel.xls");
            workbook.write(fileOutputStream);
        // 关闭流
        fileOutputStream.close();
        System.out.println("03版本Excel生成完成");

    }

生成07版本Excel的效果演示

在这里插入图片描述

在这里插入图片描述

生成07版本Excel的代码示例

public static void GenerateExcel07() throws  Exception {
        // 创建工作簿 XSSFWorkbook这里是与03版本的不同点
        Workbook workbook = new XSSFWorkbook();

        // 创建工作表 
        Sheet sheet = workbook.createSheet("07版本");

        // 创建行 第0行row0
        Row row0 = sheet.createRow(0);

        // 创建行上的单元格 第一行第一个
        Cell cell01 = row0.createCell(0);
        // 创建行上单元格 第一行第二个
        Cell cell02 = row0.createCell(1);

        // 创建行 第1行row0
        Row row1 = sheet.createRow(1);
        // 创建第二行第一个
        Cell cell11 = row1.createCell(0);
        // 创建第二行第二个
        Cell cell12 = row1.createCell(1);
        // 第二行第一个赋值
        cell11.setCellValue("小花");
        cell12.setCellValue("18");


        // 数据写入
        cell01.setCellValue("姓名");
        cell02.setCellValue("年龄");


        // 利用流生成Excel表格
        FileOutputStream fileOutputStream = new FileOutputStream("./03版本的Excel.xlsx");
            workbook.write(fileOutputStream);
        // 关闭流
        fileOutputStream.close();
        System.out.println("07版本Excel生成完成");

    }

原生POI生成Excel的速度测试

在这里插入图片描述

在EasyExcel官网中说明了POI存在的劣势与不足。那接下来我们来验证一下原生POI导出Excel的速度和内存溢出OOM问题。

生成03版本的Excel时间测试

按照03版本单个sheet数据容量上限,生成下面这部分数据花费14秒时间

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码示例

public static void GenerateExcel03() throws  Exception {
        // 创建工作簿
        Workbook workbook = new HSSFWorkbook();

        // 创建工作表
        Sheet sheet = workbook.createSheet("03版本");
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 65535; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < 255; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue("测试数据");
            }
        }
        // 记录结束时间
        long endTime = System.currentTimeMillis();
        // 利用流生成Excel表格
        FileOutputStream fileOutputStream = new FileOutputStream("./03版本生成时间测试.xls");
        workbook.write(fileOutputStream);
        // 关闭流
        fileOutputStream.close();
        System.out.println("03版本Excel生成完成");
        System.out.println("生成消耗时间" + (endTime-startTime)/1000 + "秒");

    }

生成07版本的Excel时间测试

按照03版本的生成数据页体量数据写入方式生成07版本的Excel文件。

在这里插入图片描述

在这里插入图片描述

生成07版本的Excel相较与03版本,相同数据体量的情况下。时间明显长于03版本的生成,因为在使用XSSFWorkbook,07版本的Excel会在sheet页中存在百万行单元格,但是文件的生成是通过解析数据到磁盘中生成临时文件(过程是一个DOM模型),最后将临时文件转化为Excel。该类全量读取数据到内存会可能导致OOM,还有就是在数据还没有读取完之前是不会有临时文件生成,不能生成Excel会导致实际上操作的时候很慢。

生成时间由于太慢了没有结果就先kill进程先进行后续的验证。

在这里插入图片描述

代码示例

public static void GenerateExcel07() throws  Exception {
        // 创建工作簿
        Workbook workbook = new XSSFWorkbook();

        // 创建工作表
        Sheet sheet = workbook.createSheet("07版本");
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 65535; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < 255; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue("测试数据");
            }
        }
        // 记录结束时间
        long endTime = System.currentTimeMillis();
        // 利用流生成Excel表格
        FileOutputStream fileOutputStream = new FileOutputStream("./07版本生成时间测试.xls");
        workbook.write(fileOutputStream);
        // 关闭流
        fileOutputStream.close();
        System.out.println("07版本Excel生成完成");
        System.out.println("生成消耗时间" + (endTime-startTime)/1000 + "秒");

    }

解决大数据量的写入

官方给我们提供了一个SXSSFWorkbook对象用于生成正对大数据量的生成Excel文件。

在这里插入图片描述

大数据量的写是如何解决的?

这一点在官方的文档中有涉及。翻译一下这段文字大致的意思就是正对原先的的HSSFWorkbook的实现方式是一次新读取全部的行数,有一万行那就读取一万行。那么就会很容易引发OOM问题。而SXSSFWorkbook是通过增加一个窗口的方式进行,窗口值要是不手动设置默认就是100,每次也支持读取100行数据到内存,当读取到下一个101行数据的时候,就将最早的也就是最旧的索引值刷新到磁盘的临时文件中。由此来控制内存的使用。完成数据写入之后将临时文件中的数据全部写入到Excel中,最后需要显示调用dispose()。方法来将临时文件删除。

Streaming version of XSSFWorkbook implementing the “BigGridDemo” strategy. This allows to write very large files without running out of memory as only a configurable portion of the rows are kept in memory at any one time. You can provide a template workbook which is used as basis for the written data. See https://poi.apache.org/spreadsheet/how-to.html#sxssf for details. Please note that there are still things that still may consume a large amount of memory based on which features you are using, e.g. merged regions, comments, … are still only stored in memory and thus may require a lot of memory if used extensively. SXSSFWorkbook defaults to using inline strings instead of a shared strings table. This is very efficient, since no document content needs to be kept in memory, but is also known to produce documents that are incompatible with some clients. With shared strings enabled all unique strings in the document has to be kept in memory. Depending on your document content this could use a lot more resources than with shared strings disabled. Carefully review your memory budget and compatibility needs before deciding whether to enable shared strings or not.

SXSSF (package: org.apache.poi.xssf.streaming) is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced, and heap space is limited. SXSSF achieves its low memory footprint by limiting access to the rows that are within a sliding window, while XSSF gives access to all rows in the document. Older rows that are no longer in the window become inaccessible, as they are written to the disk.

You can specify the window size at workbook construction time via new SXSSFWorkbook(int windowSize) or you can set it per-sheet via SXSSFSheet#setRandomAccessWindowSize(int windowSize)

When a new row is created via createRow() and the total number of unflushed records would exceed the specified window size, then the row with the lowest index value is flushed and cannot be accessed via getRow() anymore.

The default window size is 100 and defined by SXSSFWorkbook.DEFAULT_WINDOW_SIZE.

A windowSize of -1 indicates unlimited access. In this case all records that have not been flushed by a call to flushRows() are available for random access.

Note that SXSSF allocates temporary files that you must always clean up explicitly, by calling the dispose method.

SXSSFWorkbook defaults to using inline strings instead of a shared strings table. This is very efficient, since no document content needs to be kept in memory, but is also known to produce documents that are incompatible with some clients. With shared strings enabled all unique strings in the document has to be kept in memory. Depending on your document content this could use a lot more resources than with shared strings disabled.

Please note that there are still things that still may consume a large amount of memory based on which features you are using, e.g. merged regions, hyperlinks, comments, … are still only stored in memory and thus may require a lot of memory if used extensively.

Carefully review your memory budget and compatibility needs before deciding whether to enable shared strings or not.

The example below writes a sheet with a window of 100 rows. When the row count reaches 101, the row with rownum=0 is flushed to disk and removed from memory, when rownum reaches 102 then the row with rownum=1 is flushed, etc.

官网文档的链接:https://poi.apache.org/apidocs/5.0/

在这里插入图片描述

代码示例

public static void GenerateBigDataExcel07() throws  Exception {
        // 创建工作簿
        Workbook workbook = new SXSSFWorkbook();

        // 创建工作表
        Sheet sheet = workbook.createSheet("07大数据版本");
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 65536; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < 255; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue("测试数据");
            }
        }
        // 记录结束时间
        long endTime = System.currentTimeMillis();
        // 利用流生成Excel表格
        FileOutputStream fileOutputStream = new FileOutputStream("./07大数据版本生成时间测试.xlsx");
        workbook.write(fileOutputStream);
        // 关闭流
        fileOutputStream.close();
        // 清除临时文件
        ((SXSSFWorkbook)workbook).dispose();

        System.out.println("07大数据版本Excel生成完成");
        System.out.println("生成消耗时间" + (endTime-startTime)/1000 + "秒");

    }

读取Excel文件信息

实现读取的代码书写流程类似于生成EXCEL文件,大致上也分为七大步骤

  1. 通过文件流读取工作簿,并且这里不区分版本,一视同仁
  2. 通过文件流获取工作簿,这里需要更具不同的工作簿版本使用不同的类
  3. 获取工作表sheet
  4. 获取行单元格
  5. 获取列单元格
  6. 读取数据
  7. 关闭流

读取03版本Excel数据

效果演示

在这里插入图片描述

代码示例

  public static void ReadExcel03() throws Exception {
        // 通过文件流读取工作簿,并且这里不区分版本,一视同仁
        FileInputStream fileInputStream = new FileInputStream("03版本的Excel.xls");

        // 通过文件流获取工作簿,这里需要更具不同的工作簿版本使用不同的类
        Workbook workbook = new HSSFWorkbook(fileInputStream);

        // 获取工作表sheet
        Sheet sheet = workbook.getSheet("03版本");
//        Sheet sheet = workbook.getSheetAt(0);

        // 获取行单元格 获取第一行
        Row row = sheet.getRow(0);

        // 获取列单元格 获取第一行第一个单元格
        Cell cell = row.getCell(0);

        // 读取数据
        System.out.println("cell = " + cell);

        // 关闭流
        fileInputStream.close();
    }

读取Excel07版本的Excel数据

效果演示

在这里插入图片描述

代码展示

    public static void ReadExcel07() throws Exception {
        // 通过文件流读取工作簿,并且这里不区分版本,一视同仁
        FileInputStream fileInputStream = new FileInputStream("07版本的Excel.xlsx");

        // 通过文件流获取工作簿,这里需要更具不同的工作簿版本使用不同的类
        Workbook workbook = new XSSFWorkbook(fileInputStream);

        // 获取工作表sheet
        Sheet sheet = workbook.getSheet("07版本");
//        Sheet sheet = workbook.getSheetAt(0);

        // 获取行单元格 获取第一行
        Row row = sheet.getRow(0);

        // 获取列单元格 获取第一行第一个单元格
        Cell cell = row.getCell(0);

        // 读取数据
        System.out.println("cell = " + cell);

        // 关闭流
        fileInputStream.close();
    }

批量读取Excel中的数据

首先我们对原先生成的EXCEL进行一下字段的扩展

在这里插入图片描述

简单的批量读取03版本Excel

首先获取表头信息,接着获取表头下的具体内容信息。

效果演示

在这里插入图片描述

代码示例

public static void ReadCell03() throws Exception {
        // 通过文件流读取工作簿,并且这里不区分版本,一视同仁
        FileInputStream fileInputStream = new FileInputStream("03版本的Excel.xls");

        // 通过文件流获取工作簿,这里需要更具不同的工作簿版本使用不同的类
        Workbook workbook = new HSSFWorkbook(fileInputStream);

        // 获取工作表sheet
        Sheet sheet = workbook.getSheet("03版本");
//        Sheet sheet = workbook.getSheetAt(0);

        // 获取行单元格 获取第一行 获取标题行数据
        Row rowTitle = sheet.getRow(0);

        if (rowTitle != null) {
            // 获取标题的单元格数量
            int cellNum = rowTitle.getPhysicalNumberOfCells();
            for (int i = 0; i < cellNum; i++) {
                // 获取所有单元格
                Cell cell = rowTitle.getCell(i);
                if (cell != null) {
                    // 获取单元格数量
                    String value = cell.getStringCellValue();
                    System.out.println(value + "|");
                }
            }
        }

        // 获取内容行数据
        int rowNum = sheet.getPhysicalNumberOfRows();
        // 从第二行开始获取内容行数据
        for (int i = 1; i < rowNum; i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                // 获取当前行一共有多少单元格
                int cellNum = row.getPhysicalNumberOfCells();
                // 获取当前行中单元格的数据
                for (int j = 0; j < cellNum; j++) {
                    Cell cell = row.getCell(j);
                    if (cell != null) {
                        // 获取单元格数据类型
                        CellType cellType = cell.getCellType();
                        // 根据不同数据类型获取数据
                        String cellValue = "";
                        switch (cellType){
                            // 字符串
                            case STRING:
                                cellValue = cell.getStringCellValue();
                                System.out.println(cellValue);
                                System.out.println("字符串类型");
                                break;
                            // 数值类型:包括整数、小数、日期
                            case NUMERIC:
                                // 判断是否为日期类型
                                if (DateUtil.isCellDateFormatted(cell)){
                                    Date date = cell.getDateCellValue();
                                    cellValue = new SimpleDateFormat("yyyy-MM-dd").format(date);
                                    System.out.println(cellValue);
                                    System.out.println("日期类型");
                                }else {
                                    cellValue = cell.toString();
                                    System.out.println(cellValue);
                                    System.out.println("整数或小数类型");
                                }
                                break;
                            // 空白单元格类型
                            case BLANK:
                                System.out.println("空白单元格");
                                break;
                            case BOOLEAN:
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                System.out.println(cellValue);
                                System.out.println("布尔类型");
                                break;
                            case ERROR:
                                System.out.println("错误类型");
                                break;
                        }
                    }
                }
            }

        }


        // 关闭流
        fileInputStream.close();
    }

简单的批量读取07版本Excel

这里有一个问题就是在使用代码自动导出EXCEL之后设置导出文件的单元格熟悉,原有的单元格熟悉不会因为你修改了单元格熟悉而改变。

效果演示

在这里插入图片描述

代码示例

 public static void ReadCell07() throws Exception {
        // 通过文件流读取工作簿,并且这里不区分版本,一视同仁
        FileInputStream fileInputStream = new FileInputStream("07版本的Excel.xlsx");

        // 通过文件流获取工作簿,这里需要更具不同的工作簿版本使用不同的类
        Workbook workbook = new XSSFWorkbook(fileInputStream);

        // 获取工作表sheet
        Sheet sheet = workbook.getSheet("07版本");
//        Sheet sheet = workbook.getSheetAt(0);

        // 获取行单元格 获取第一行 获取标题行数据
        Row rowTitle = sheet.getRow(0);

        if (rowTitle != null) {
            // 获取标题的单元格数量
            int cellNum = rowTitle.getPhysicalNumberOfCells();
            for (int i = 0; i < cellNum; i++) {
                // 获取所有单元格
                Cell cell = rowTitle.getCell(i);
                if (cell != null) {
                    // 获取单元格数量
                    String value = cell.getStringCellValue();
                    System.out.println(value + "|");
                }
            }
        }

        // 获取内容行数据
        int rowNum = sheet.getPhysicalNumberOfRows();
        // 从第二行开始获取内容行数据
        for (int i = 1; i < rowNum; i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                // 获取当前行一共有多少单元格
                int cellNum = row.getPhysicalNumberOfCells();
                // 获取当前行中单元格的数据
                for (int j = 0; j < cellNum; j++) {
                    Cell cell = row.getCell(j);
                    if (cell != null) {
                        // 获取单元格数据类型
                        CellType cellType = cell.getCellType();
                        // 根据不同数据类型获取数据
                        String cellValue = "";
                        switch (cellType){
                            // 字符串
                            case STRING:
                                cellValue = cell.getStringCellValue();
                                System.out.println(cellValue);
                                System.out.println("字符串类型");
                                break;
                            // 数值类型:包括整数、小数、日期
                            case NUMERIC:
                                // 判断是否为日期类型
                                if (DateUtil.isCellDateFormatted(cell)){
                                    Date date = cell.getDateCellValue();
                                    cellValue = new SimpleDateFormat("yyyy-MM-dd").format(date);
                                    System.out.println(cellValue);
                                    System.out.println("日期类型");
                                }else {
                                    cellValue = cell.toString();
                                    System.out.println(cellValue);
                                    System.out.println("整数或小数类型");
                                }
                                break;
                            // 空白单元格类型
                            case BLANK:
                                System.out.println("空白单元格");
                                break;
                            case BOOLEAN:
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                System.out.println(cellValue);
                                System.out.println("布尔类型");
                                break;
                            case ERROR:
                                System.out.println("错误类型");
                                break;
                        }
                    }
                }
            }

        }


        // 关闭流
        fileInputStream.close();
    }

EasyExcel导出Excel

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

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

相关文章

Elasticsearch【安装ES服务、安装kibana、Docker安装 、索引操作、文档操作】(二)-全面详解(学习总结---从入门到深化)

目录 Elasticsearch安装_安装ES服务 Elasticsearch安装_安装kibana Elasticsearch安装_Docker安装 Elasticsearch常用操作_索引操作 Elasticsearch常用操作_文档操作 Elasticsearch安装_安装ES服务 准备工作 1、 准备一台搭载有CentOS7系统的虚拟机&#xff0c;使用XSh…

(转载)支持向量机(SVM)的回归拟合(matlab实现)

与传统的神经网络相比&#xff0c;SVM具有以下几个优点&#xff1a; (1)SVM是专门针对小样本问题而提出的&#xff0c;可以在有限样本的情况下获得最优解。 (2)SVM算法最终将转化为一个二次规划问题&#xff0c;从理论上讲可以得到全局最优解&#xff0c;从而解决了传统神经网…

Python GUI编程利器:Tkinker中的布局管理器(10)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日目标 学习Tkinter的三个布局管理器&#xff1a; pack布局管理器 gird布局管理器 place布局管理器 啥是布局管理器&am…

TCP流套接字编程(模拟多个客户端与服务器交互)

目录 一、ServerSocket API 1.1、ServerSocket构造方法 1.2、ServerSocket方法 二、Socket API 2.1、socket构造方法 2.2、socket方法 三、TCP 中的长短连接 四、示例 实现聊天室功能 五、存在的问题 一、ServerSocket API ServerSocket 是创建TCP服务端Socket的…

500个线程运行串行原因排查

场景&#xff1a;项目中有业务需要开启500个线程执行&#xff0c;需要证明有500个线程在执行。用的是一台128核的电脑。服务用docker启动的。所以理论上应该是要有128个线程并行执行的。 目录 一.证明有500个线程在执行(会发现并行度很低) 1.用top命令监控进程内的线程运行情…

netty学习(5):netty实现注册中心和发送JSON数据到指定的客户端

1. 实现&#xff1a;在netty客户端实现netty客户端注册功能&#xff0c;netty客户端需要发送注册消息到netty服务端。 2. 在父工程创建Message类&#xff0c;定义消息格式和消息类型 定义消息类型&#xff1a; package message;public enum MessageType {RegisterRequest,Re…

函数重载与函数递归

一、函数重载 定义&#xff1a;两个函数的函数名称相同&#xff0c;但是参数的个数或者类型不同 参考以下代码&#xff1a; //1.public static int add(int x,int y){return x y;}//2.与1构成重载public static int add(byte a,int b){return a b;}//3.与1构成重载public s…

文件上传漏洞总结

文件上传 文件上传漏洞产生的原理 文件上传漏洞是指用户通过界面上的上传功能上传了一个可执行的脚本文件&#xff0c;而WEB端的系统并未对其进行检测或者检测的逻辑做的不够好。 文件上传漏洞的危害 1、由于是上传的文件&#xff0c;所以文件由用户决定&#xff0c;上传we…

交换机架构整理

网口的基本结构 网口扫盲三:以太网芯片MAC和PHY的关系 问:如何实现单片以太网微控制器? 问:以太网MAC是什么? 问:什么是MII? 问:以太网PHY是什么? 问:造成以太网MAC和PHY单片整合难度高的原因是什么? 问: 网卡上除RJ-45接口外,还需要其它元件吗? 问:10BaseT和100BaseTX…

LeetCode[面试题17.14]最小的K个数

难度&#xff1a;中等 题目&#xff1a; 设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。 示例&#xff1a; 输入&#xff1a; arr [1,3,5,7,2,4,6,8], k 4 输出&#xff1a; [1,2,3,4]提示&#xff1a; 0 < len(arr) < 1000000 <…

Java设计模式之创建型-建造者模式(UML类图+案例分析)

目录 一、基本概念 二、UML类图 三、角色设计 四、案例分析 五、总结 一、基本概念 建造者模式是一种创建型设计模式&#xff0c;它使我们将一个复杂对象的构建步骤分离出来&#xff0c;使得同样的构建过程可以创建不同的表示。该模式的目的是将构建复杂对象的过程抽象化…

JavaScrpt_13 Web API 正则表达式

JavaScrpt_13 Web API 正则表达式 一、 正则表达式1. 正则基本使用2. 元字符边界符量词范围字符类 3. 替换和修饰符4. change 事件5. 判断是否有类 一、 正则表达式 正则表达式&#xff08;Regular Expression&#xff09;是一种字符串匹配的模式&#xff08;规则&#xff09;…

12_Linux异步通知

目录 异步通知简介 驱动中的信号处理 应用程序对异步通知的处理 驱动程序编写 编写测试APP 运行测试 异步通知简介 在使用阻塞或者非阻塞的方式来读取驱动中按键值都是应用程序主动读取的,对于非阻塞方式来说还需要应用程序通过poll函数不断的轮询。最好的方式就是驱动…

【Python爬虫与数据分析】时间、日期、随机数标准库

目录 一、模块化概述 二、time库 1. 时间获取 2. 时间格式化 3. 程序计时 三、datetime库 1. datetime.datetime类 2. datetime.timedelta类 四、random库 1. 基本随机函数 2. 扩展随机函数 3. 随机时间的生成 一、模块化概述 Python程序由模块组成&#xff0c;一个…

MySQL基础篇第4章(运算符)

文章目录 1、算术运算符1.1 加法与减法运算符1.2 乘法与除法运算符1.3 求模&#xff08;求余&#xff09;运算符 2、比较运算符2.1 等号运算符2.2 安全等于<>2.3 不等于运算符2.4 空运算符2.5 非空运算符2.6 最小值运算符2.7 最大值运算符2.8 BETWEEN AND运算符2.9 IN运算…

typeScript(持续吐血版)

typeScript-02-进阶(TSVue3) 结合vue3来使用TypeScript 使用vite来创建vue3TS的项目 使用vite创建项目&#xff0c;并选择带ts的版本 npm create vitelatest my-vue-ts-app – --template vue-ts 参考链接&#xff1a;https://vuejs.org/guide/typescript/composition-api…

7.软件是怎么样炼成的:c++编译器过程

"重新生成解决方案"&#xff0c;"调试"的背后的四个阶段 故事&#xff1a; 渣男是有套路和步骤的。 代码变成软件也是有固定的套路的 总结&#xff1a; 1.预处理 g -e源程序&#xff0c;-o生成的结果。后面的a.cpp是新的源文件。这个时候还是源程序计算…

leetcode-977. 有序数组的平方

leetcode-977. 有序数组的平方 文章目录 leetcode-977. 有序数组的平方一.题目描述二.第1次提交(std::sort)三.第2次提交(左右指针) 一.题目描述 二.第1次提交(std::sort) class Solution {public:vector<int> sortedSquares(vector<int> &nums) {for (int i …

Centos或Linux编写一键式Shell脚本删除用户、组指导手册

文章目录 一、目的二、操作步骤 一、目的 本指导手册为了更加方便使用Centos或者Linux&#xff0c;并在里面删除用户、用户组。 注意点1&#xff1a;userdel命令删除该用户时&#xff0c;并不能删除该用户的所有信息&#xff0c;只是删除了/etc/passwd、/etc/shadow、/etc/gr…

Vue3 +TScript 基本开发

首先你要使用 vite 创建项目 npm init vuelatest 并选择带ts的版本 文件的结构 main.ts 文件 import { createApp } from "vue" import { createPinia } from piniaimport App from "./App.vue" const pinia createPinia() const app createApp(App)a…