【EasyExcel】复杂导出操作-自定义颜色样式等(版本3.1.x)

文章目录

  • 前言
  • 一、自定义拦截器
  • 二、自定义操作
    • 1.自定义颜色
    • 2.合并单元格
  • 三、复杂操作示例
    • 1.实体(使用了注解式样式):
    • 2.自定义拦截器
    • 3.代码
    • 4.最终效果


前言

本文简单介绍阿里的EasyExcel的复杂导出操作,包括自定义样式,根据数据合并单元格等。

点击查看EasyExcel官方文档


一、自定义拦截器

要实现复杂导出,靠现有的拦截器怕是不大够用,EasyExcel 已经有提供部分像是 自定义样式的策略HorizontalCellStyleStrategy
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
通过源码,我们不难发现其原理正是实现了拦截器接口,使用了afterCellDispose方法,在数据写入单元格后会调用该方法,因此,需要进行复杂操作,我们需要自定义拦截器,在afterCellDispose方法进行逻辑处理,其中我们可以通过context参数获取到表,行,列及单元格数据等信息:
在这里插入图片描述

二、自定义操作

1.自定义颜色

由于WriteCellStyle 及CellStyle接口的设置单元格背景颜色方法setFillForegroundColor不支持自定义颜色,我在网上找了半天,以及询问阿里自家ai助手通义得到的答案都是往里塞一个XSSFColor这样的答案,但这个方法传参是一个short类型的index呀,是预设好的颜色,里面也没有找到其他重载方法。(这里针对的是导出xlsx文件)

在这里插入图片描述

而真正可以自定义颜色的是XSSFCellStyle类,XSSFCellStyle实现CellStyle接口,并重载了该方法,于是我们只需要在workbook.createCellStyle()的时候将其强转为XSSFCellStyle:

// 将背景设置成浅蓝色
XSSFColor customColor = new XSSFColor(new java.awt.Color(181, 198, 234), null);
XSSFCellStyle style = (XSSFCellStyle)workbook.createCellStyle();
style.setFillForegroundColor(customColor);
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell.setCellStyle(style);

在idea我们可以使用 ctrl + alt + 鼠标点击接口,来查看接口的所有实现类(HSSF是针对xls的):

在这里插入图片描述

然而在我们自定义的拦截器中,操作当前单元格样式时会无法生效,这是因为在3.1.x版本后有一个FillStyleCellWriteHandler拦截器,他会把OriginCellStyle和WriteCellStyle合并,会已WriteCellStyle样式为主,他的order是50000,而我们自定义的拦截器默认是0,因此我们修改的样式会被覆盖。
在这里插入图片描述
在这里插入图片描述
解决方法很简单,我们可以在我们的自定义拦截器重写order方法,将其值设置大于50000即可

  @Override
  public int order() {
      return 50001;
  }

如果你没有使用自定义拦截器(如HorizontalCellStyleStrategy )以及没有设置WriteCellStyle 样式,则还可以将ignoreFillStyle置为true,

 @Override
 public void afterCellDispose(CellWriteHandlerContext context) {
 	 context.setIgnoreFillStyle(true);
 	 // 做其他样式操作
 }
 

2.合并单元格

 ```java
 @Override
 public void afterCellDispose(CellWriteHandlerContext context) {
 	 // 判断当前为表头,不执行操作
     if (isHead) {
            log.info("\r\n当前为表头, 不执行操作");
            return;
     }
     // 获取当前单元格
     context.getCell()
     // 当前 Sheet
     Sheet sheet = cell.getSheet();
     // 当前单元格所在行索引
     int rowIndexCurr = cell.getRowIndex();
     // 当前单元格所在列索引
     int columnIndex = cell.getColumnIndex();
     // 当前单元格所在行的上一行索引
     int rowIndexPrev = rowIndexCurr - 1;
     // 当前单元格所在行的 Row 对象
     Row rowCurr = cell.getRow();
     // 当前单元格所在行的上一行 Row 对象
     Row rowPrev = sheet.getRow(rowIndexPrev);
     // 当前单元格的上一行同列单元格
     Cell cellPrev = rowPrev.getCell(columnIndex);
	 // 合并同列不同行的相邻两个单元格
     sheet.addMergedRegion(new CellRangeAddress(rowIndexPrev, rowIndexCurr,columnIndex, columnIndex));
 	 
 }
 

需要注意的是,如果要合并的单元格已经被其他单元格合并过,则不能直接使用这个合并方法,需要先解除合并,再进行组合合并:

 // 从 Sheet 中,获取所有合并区域
 List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
 // 判断是否合并过
 boolean merged = false;
 // 遍历合并区域集合
 for (int i = 0; i < mergedRegions.size(); i++) {
     CellRangeAddress cellAddresses = mergedRegions.get(i);
     // 判断 cellAddress 的范围是否是从 rowIndexPrev 到 cell.getColumnIndex()
     if (cellAddresses.isInRange(rowIndexPrev, cell.getColumnIndex())) {
         // 解除合并
         sheet.removeMergedRegion(i);
         // 设置范围最后一行,为当前行
         cellAddresses.setLastRow(rowIndexCurr);
         // 重新进行合并
         sheet.addMergedRegion(cellAddresses);
         merged = true;
         break;
     }
 }
 // merged=false,表示当前单元格为第一次合并
 if (!merged) {
     CellRangeAddress cellAddresses = new CellRangeAddress(rowIndexPrev, rowIndexCurr, cell.getColumnIndex(), cell.getColumnIndex());
     sheet.addMergedRegion(cellAddresses);
 }

三、复杂操作示例

自定义拦截器代码如下(示例):

1.实体(使用了注解式样式):

package com.mhqs.demo.tool.easyExcel.entity;


import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentFontStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.math.BigDecimal;

/**
 * 账单实体类
 * @author 棉花
 * */
@Data
@EqualsAndHashCode(callSuper = false)
@HeadFontStyle(fontHeightInPoints = 10)
@HeadRowHeight(27)
@ColumnWidth(13)
@ContentFontStyle(fontName = "宋体",fontHeightInPoints = 11)
public class DemoEntity extends EasyExcelEntity {

    @ExcelProperty({"账期"})
    private String settlePeriod;

    @ExcelProperty({"服务商"})
    private String stockCreatorMchid;

    @ExcelProperty({"地区"})
    private String place;

    @ExcelProperty({"金额(元)"})
    private BigDecimal consumeAmount;

    public DemoEntity(String settlePeriod, String stockCreatorMchid,String place, BigDecimal consumeAmount){
        this.settlePeriod = settlePeriod;
        this.stockCreatorMchid = stockCreatorMchid;
        this.place = place;
        this.consumeAmount = consumeAmount;
    }

}


2.自定义拦截器

package com.mhqs.demo.tool.easyExcel.handler;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.StyleUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.mhqs.demo.tool.easyExcel.entity.DemoEntity;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author bcb
 * 账单导出样式处理
 */
public class CustomCellWriteHandler implements CellWriteHandler {

    /**
     * 自定义颜色
     */
    private final java.awt.Color color;
    /**
     * 自定义颜色样式
     */
    private CellStyle colorfulCellStyle;
    /**
     * 自定义特殊金额样式
     */
    private CellStyle specialCellStyle;
    /**
     * 头样式
     */
    private final WriteCellStyle headWriteCellStyle;

    /**
     * 内容样式
     */
    private final WriteCellStyle contentWriteCellStyle;

    /**
     * 头样式(可自定义颜色)
     */
    private CellStyle headCellStyle;

    /**
     * 内容样式(可自定义颜色)
     */
    private CellStyle contentCellStyle;

    public CustomCellWriteHandler(WriteCellStyle headWriteCellStyle,WriteCellStyle contentWriteCellStyle, java.awt.Color color) {
        this.headWriteCellStyle = headWriteCellStyle;
        this.contentWriteCellStyle = contentWriteCellStyle;
        this.color = color;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
        // 在创建单元格之前的操作(如果需要)
        Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
        if (colorfulCellStyle == null) {
            colorfulCellStyle = createColorfulCellStyle(workbook);
        }
        // 合并样式(以WriteCellStyle为主)
        headCellStyle = StyleUtil.buildCellStyle(workbook, colorfulCellStyle, headWriteCellStyle);
        contentCellStyle = StyleUtil.buildCellStyle(workbook, workbook.createCellStyle(), contentWriteCellStyle);

    }
    /*
    * 创建自定义颜色样式
    */
    private CellStyle createColorfulCellStyle(Workbook workbook) {
        XSSFColor customColor = new XSSFColor(color, null);
        XSSFCellStyle style = (XSSFCellStyle)workbook.createCellStyle();
        // 设置自定义颜色
        style.setFillForegroundColor(customColor);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        // 设置垂直对齐方式
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置水平对齐方式
        style.setAlignment(HorizontalAlignment.CENTER);
        return style;
    }

    /*
     * 创建自定义特殊金额样式
     */
    private CellStyle createSpecialCellStyle(Workbook workbook) {
        if (specialCellStyle == null) {
            XSSFCellStyle style = (XSSFCellStyle)createColorfulCellStyle(workbook);
            Font font = workbook.createFont();
            // 字体加粗
            font.setBold(true);
            style.setFont(font);
            specialCellStyle = style;
        }
        return specialCellStyle;
    }


    /**
     * 在 Cell 写入后处理
     *
     * @param writeSheetHolder
     * @param writeTableHolder
     * @param cellDataList
     * @param cell               当前 Cell
     * @param head
     * @param relativeRowIndex   表格内容行索引,从除表头的第一行开始,索引为0
     * @param isHead             是否是表头,true表头,false非表头
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 当前 Sheet
        Sheet sheet = cell.getSheet();
        // 判断当前为表头,执行对应样式操作
        if (isHead) {
            cell.setCellStyle(headCellStyle);
        } else {
            cell.setCellStyle(contentCellStyle);
        }
        // 判断当前为表头,不执行操作
        if (isHead || relativeRowIndex == 0) {
            return;
        }
        int columnIndex = cell.getColumnIndex();
        // 当前 Cell 所在行索引
        int rowIndexCurr = cell.getRowIndex();
        // 当前 Cell 所在行的上一行索引
        int rowIndexPrev = rowIndexCurr - 1;
        // 当前 Cell 所在行的 Row 对象
        Row rowCurr = cell.getRow();
        // 当前 Cell 所在行的上一行 Row 对象
        Row rowPrev = sheet.getRow(rowIndexPrev);
        // 当前单元格的上一行同列单元格
        Cell cellPrev = rowPrev.getCell(columnIndex);
        // 当前单元格的值
        Object cellValueCurr = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        if (columnIndex == 3 && cellValueCurr != null && (double)cellValueCurr > 200) {
            // 判断金额大于200就设置特定颜色并加粗,并将上一列同一行的数据也设置特定颜色
            CellStyle cellStyle = createSpecialCellStyle(sheet.getWorkbook());
            cell.setCellStyle(cellStyle);
            // 当前单元格的同行上一列单元格
            Cell cellPreC = rowCurr.getCell(columnIndex - 1);
            cellPreC.setCellStyle(colorfulCellStyle);

        }
        // 上面单元格的值
        Object cellValuePrev = cellPrev.getCellType() == CellType.STRING ? cellPrev.getStringCellValue() : cellPrev.getNumericCellValue();
        /*
         * 只判断前两列相同行数据
         */
        if (columnIndex != 0 && columnIndex != 1) {
            return;
        }
        // 判断当前单元格与上面单元格是否相等,不相等不执行操作
        if (!cellValueCurr.equals(cellValuePrev)) {
            return;
        }
        /*
         * 当第一列上下两个单元格不一样时,说明不是一个账期数据
         */
        if (!rowPrev.getCell(0).getStringCellValue().equals(rowCurr.getCell(0).getStringCellValue())) {
            return;
        }
        // 从 Sheet 中,获取所有合并区域
        List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
        // 是否合并过
        boolean merged = false;
        // 遍历合并区域集合
        for (int i = 0; i < mergedRegions.size(); i++) {
            CellRangeAddress cellAddresses = mergedRegions.get(i);
            //判断 cellAddress 的范围是否是从 rowIndexPrev 到 cell.getColumnIndex()
            if (cellAddresses.isInRange(rowIndexPrev, columnIndex)) {
                // 从集合中移除
                sheet.removeMergedRegion(i);
                // 设置范围最后一行,为当前行
                cellAddresses.setLastRow(rowIndexCurr);
                // 重新添加到 Sheet 中
                sheet.addMergedRegion(cellAddresses);
                // 已完成合并
                merged = true;
                break;
            }
        }
        // merged=false,表示当前单元格为第一次合并
        if (!merged) {
            CellRangeAddress cellAddresses = new CellRangeAddress(rowIndexPrev, rowIndexCurr, columnIndex, columnIndex);
            sheet.addMergedRegion(cellAddresses);
        }
    }

    /**
     * 获取当前处理器优先级
     */
    @Override
    public int order() {
        return 50001;
    }


}

3.代码



  public static void main(String[] args) {

      String fileName = "D:\\temp\\账单.xlsx";
      // 设置 Cell 样式
      WriteCellStyle writeCellStyle = new WriteCellStyle();
      // 设置垂直对齐方式
      writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
      // 设置水平对齐方式
      writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
      // 设置边框
      writeCellStyle.setBorderTop(BorderStyle.THIN);
      writeCellStyle.setBorderBottom(BorderStyle.THIN);
      writeCellStyle.setBorderLeft(BorderStyle.THIN);
      writeCellStyle.setBorderRight(BorderStyle.THIN);
      // 自定义颜色
      java.awt.Color color = new java.awt.Color(181, 198, 234);
      List<DemoEntity> dataList = new ArrayList<>();
      for (int i = 0; i < 5; i++) {
          dataList.add(new DemoEntity("202301","服务商" + i%2,"地区" + i,new BigDecimal(i * 100)));
      }
      dataList.sort(Comparator.comparing(DemoEntity::getSettlePeriod).thenComparing(DemoEntity::getStockCreatorMchid));

      ExcelWriter excelWriter = EasyExcel.write(fileName, DemoEntity.class).build();
      WriteSheet writeSheet = EasyExcel.writerSheet(0, "账单")
              .registerWriteHandler(new CustomCellWriteHandler(null,writeCellStyle,color))
              .build();
      excelWriter.write(dataList, writeSheet);
	// 需要多sheet则可以继续
	// WriteSheet writeSheet2 = EasyExcel.writerSheet(1, "第二个sheet")

      excelWriter.finish();
  }



4.最终效果

在这里插入图片描述

待续…


参考文章:
easyexcel 3.1.0+,设置RBG背景颜色
EasyExcel导出多sheet并设置单元格样式
EasyExcel的CellWriteHandler注入CellStyle不生效

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

集群搭建高可用

contos7.9 部署3节点 hadoop3.4 高可用集群 contos7.9 部署3节点 hadoop3.4 高可用集群环境信息Hadoop与Zookeeper的版本对应关系服务器角色分配使用端口服务器配置配置免密登录服务器配置初始化 init_server.sh配置主机名映射所有节点配置 hosts文件 hadoop 安装环境配置下载安…

Pycharm 配置 Poetry

Python 环境安装 参考以下&#xff1a; 官网安装步骤 CODA方式安装 Poetry 安装 Poetry在windows下的安装使用 1.下载软件包 下载地址 2.获取安装脚本下载地址 3.使用命令安装 打开cmd&#xff0c;进入安装包和脚本文件所在目录&#xff0c;执行命令&#xff1a; python …

卡尔曼滤波:从理论到应用的简介

卡尔曼滤波&#xff08;Kalman Filter&#xff09;是一种递归算法&#xff0c;用于对一系列噪声观测数据进行动态系统状态估计。它广泛应用于导航、控制系统、信号处理、金融预测等多个领域。本文将介绍卡尔曼滤波的基本原理、核心公式和应用案例。 1. 什么是卡尔曼滤波&#x…

聊聊Flink:Flink的运行时架构

一、运行时架构 上一篇我们可以看到Flink的核心组件的Deploy层&#xff0c;该层主要涉及了Flink的部署模式&#xff0c;Flink支持多种部署模式&#xff1a;本地、集群&#xff08;Standalone/YARN&#xff09;、云&#xff08;GCE/EC2&#xff09;。 Local&#xff08;本地&am…

元器件封装

元器件封装类型 为什么越来越多用贴片元件&#xff0c;而不是插件元件 为什么越来越多用贴片元件&#xff0c;而不是插件元件 1.体积小、质量小、容易保存和运输&#xff1b; 2.容易焊接和拆卸。抗震效果好。 贴片元件不用过孔&#xff0c;用锡少。直插元件最麻烦的就是拆卸&a…

[JAVAEE] 网络编程

目录 一. 什么是socket套接字 二. socket套接字 2.1 socket套接字根据传输层协议分类 2.2 TCP流套接字 UDP数据报套接字主要特点 三. UDP数据报套接字编程 3.1 DatagramSocket 是UDP socket, 用于发送和接受数据报 3.2 DatagramPacket 是UDP socket 发送和接收的数据报 …

GNN入门案例——KarateClub结点分类

文章目录 一、任务描述二、环境配置三、加载数据四、定义网络结构五、训练模型 一、任务描述 Karate Club 图任务是一个经典的图结构学习问题&#xff0c;通常用于社交网络分析和社区检测。该数据集是由 Wayne W. Zachary 在1977年收集的&#xff0c;描述了一个美国的空手道俱…

173. 二叉搜索树迭代器【 力扣(LeetCode) 】

文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 173. 二叉搜索树迭代器 一、题目描述 实现一个二叉搜索树迭代器类BSTIterator &#xff0c;表示一个按中序遍历二叉搜索树&#xff08;BST&#xff09;的迭代器&#xff1a; BSTIterato…

【lamafactory BLEU ROUGLE L评测】

1、BLEU/ROUGLE评测界面 2、这个是用BLEU 和ROUGL来评测 目录&#xff1a;saves/Qwen2-7B-Chat/lora/eval_2024-11-14-16-28-19/ 在saves文件夹 生成的文件如下 all_results.json文件 说明模型在这个测试集上是不好的 3、可以查看预测结果的文件 predict_result.json

前端开发中常用的包管理器(npm、yarn、pnpm、bower、parcel)

文章目录 1. npm (Node Package Manager)2. Yarn (Yarn Package Manager)3. pnpm4. Bower5. Parcel总结 前端开发中常用的包管理器主要有以下几个&#xff1a; 1. npm (Node Package Manager) 简介&#xff1a; npm 是 Node.js 的默认包管理器&#xff0c;也是最广泛使用的包…

Python爬虫项目 | 一、网易云音乐热歌榜歌曲

文章目录 1.文章概要1.1 实现方法1.2 实现代码1.3 最终效果 2.具体讲解2.1 使用的Python库2.2 代码说明2.2.1 创建目录保存文件2.2.2 爬取网易云音乐热歌榜单歌曲 2.3 过程展示 3 总结 1.文章概要 学习Python爬虫知识&#xff0c;实现简单的一个小案例&#xff0c;网易云音乐热…

SHELL脚本(Linux)

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

reduce-scatter:适合分布式计算;Reduce、LayerNorm和Broadcast算子的执行顺序对计算结果的影响,以及它们对资源消耗的影响

目录 Gather Scatter Reduce reduce-scatter:适合分布式计算 Reduce、LayerNorm和Broadcast算子的执行顺序对计算结果的影响,以及它们对资源消耗的影响 计算结果理论正确性 资源消耗方面 Gather 这个也很好理解,就是把多个进程的数据拼凑在一起。 Scatter 不同于Br…

arkUI:水果选择与管理:基于 ArkUI 的长按编辑功能实现

水果选择与管理&#xff1a;基于 ArkUI 的长按编辑功能实现 1 主要内容说明2 相关内容2.1 相关内容2.1.1 源码1内容的相关说明2.1.1.1 数据结构与状态管理2.1.1.2 添加水果功能2.1.1.3 水果列表展示2.1.1.4 长按进入编辑模式2.1.1.5 复选框的多选功能2.1.1.6 删除水果功能2.1.1…

(时序论文阅读)TimeMixer: Decomposable Multiscale Mixing for Time Series Forecasting

来源论文iclr2024 论文地址&#xff1a;https://arxiv.org/abs/2405.14616 源码地址&#xff1a; https://github.com/kwuking/TimeMixer 背景 数据是有连续性&#xff0c;周期性&#xff0c;趋势性的。我们这篇文章主要围绕的是用MLP结构来预测数据的周期性具体为&#xff…

聊天服务器(8)用户登录业务

目录 登录状态业务层代码数据模型层代码记录用户的连接信息以及线程安全问题客户端异常退出业务 登录状态 登录且状态变为online 业务层代码 #include "chatservice.hpp" #include "public.hpp" #include <string> #include <muduo/base/Loggi…

18.UE5怪物视野、AI感知、攻击范围、散弹技能

2-20 怪物视野、AI感知、攻击范围、散弹技能_哔哩哔哩_bilibili 目录 1.AI感知组件 2.AI感知更新的函数 3.攻击范围 4.散弹技能 4.1创建发射物 4.2创建远程攻击方式 4.3散弹自定义事件的实现 4.4动画通知实现攻击 1.AI感知组件 为怪物蓝图添加AI感知组件&#xff0c;…

单片机智能家居火灾环境安全检测

目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 电路图采用Altium Designer进行设计&#xff1a; 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 在现代社会&#xff0c;火灾安全始终是人们关注的重点问题。随着科技的不…

安全见闻1-5

涵盖了编程语言、软件程序类型、操作系统、网络通讯、硬件设备、web前后端、脚本语言、病毒种类、服务器程序、人工智能等基本知识&#xff0c;有助于全面了解计算机科学和网络技术的各个方面。 安全见闻1 1.编程语言简要概述 C语言&#xff1a;面向过程&#xff0c;适用于系统…

【计算机网络】TCP协议特点3

心跳机制 什么是心跳机制 心跳机制是在计算机系统、网络通信和许多其他技术领域广泛应用的一种机制&#xff0c;用于检测两个实体之间的连接是否仍然活跃&#xff0c;或者设备是否还在正常运行。就是每隔一段时间发送一个固定的消息给服务端&#xff0c;服务端回复一个固定…