POI和EasyExcel学习

1.POI

1.1POI简介

在Java中,POI是指Apache POI(Poor Obfuscation Implementation),它是一个开源的Java库,用于处理Microsoft Office文档格式文件,如Excel、Word、PowerPoint等。POI提供了一组API,使得开发者可以通过Java代码读取、写入和修改Office文档,可以方便地操作Excel表格、Word文档、PowerPoint演示文稿等。

POI主要包括以下三个组件:

  1. POI-HSSF:用于操作Excel2003及以前版本的.xls格式文件。

  2. POI-XSSF:用于操作Excel2007及以后版本的.xlsx格式文件。

  3. POI-HWPF:用于操作Word97-2003版本的.doc格式文件。

  4. POI-HSLF:提供读写Microso PowerPointr格式档案的功能。

  5. HDGF - 提供读写MicrosoftVisio格式档案的功能。

除了这5个主要的组件,POI还提供了其他的组件,例如POI-XWPF用于操作Word2007及以后版本的.docx格式文件、POI-HSLF用于操作PowerPoint文档等等。

使用POI,开发者可以读取Excel表格数据、创建新的Excel表格、编辑已有的Excel表格、读取Word文档内容等等。同时,POI也支持将文档导出为PDF、HTML等格式。

1.2Excel的区别

注意:03和07版本存在兼容性问题,03版本最多只能有65535行

03和07版本的写方法是一样的,但是对象不同。

1.工作簿:

2.工作表:

3.行:

4.列:

1.3POI-Excel写

1.3.1依赖导入

    <!--导入依赖--><dependencies><!--xls(03)--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version></dependency><!--xlsx(07)--><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency><!--日期格式化工具--><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.14</version></dependency><!--test--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>

1.3.2 03版本

   //03版本@Testpublic void testWrite()  {//1.创建一个工作簿Workbook workbook = new HSSFWorkbook();//2.创建一个工作表Sheet sheet = workbook.createSheet("测试表");//3.创建一个行(1,1)Row row1 = sheet.createRow(0);//4.创建一个单元格1Cell cell11 = row1.createCell(0);cell11.setCellValue("表头1");Cell cell12 = row1.createCell(1);cell12.setCellValue("001");//第二行(2,1)Row row2 = sheet.createRow(1);Cell cell21 = row2.createCell(0);cell21.setCellValue("统计时间");Cell cell22 = row2.createCell(1);String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell22.setCellValue(time);//生成表(Io流) 03版本 xlsFileOutputStream outputStream = null;try {outputStream = new FileOutputStream(PATH + "测试表.xls");} catch (FileNotFoundException e) {throw new RuntimeException(e);}//输出try {workbook.write(outputStream);} catch (IOException e) {throw new RuntimeException(e);}//关闭流try {outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}System.out.println("文件生成完毕!");}

1.3.3 07版本

    //07版本@Testpublic void testWrite07()  {//1.创建一个工作簿Workbook workbook = new XSSFWorkbook();//2.创建一个工作表Sheet sheet = workbook.createSheet("测试表");//3.创建一个行(1,1)Row row1 = sheet.createRow(0);//4.创建一个单元格1Cell cell11 = row1.createCell(0);cell11.setCellValue("表头1");Cell cell12 = row1.createCell(1);cell12.setCellValue("001");//第二行(2,1)Row row2 = sheet.createRow(1);Cell cell21 = row2.createCell(0);cell21.setCellValue("统计时间");Cell cell22 = row2.createCell(1);String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell22.setCellValue(time);//生成表(Io流) 07版本 xlsxFileOutputStream outputStream = null;try {outputStream = new FileOutputStream(PATH + "测试表.xlsx");} catch (FileNotFoundException e) {throw new RuntimeException(e);}//输出try {workbook.write(outputStream);} catch (IOException e) {throw new RuntimeException(e);}//关闭流try {outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}System.out.println("文件生成完毕!");}

注意对象的区别和文件后缀

1.4 大文件写入

数据批量导入!

大文件写HSSF:

缺点:最多只能处理65536行,否则就会抛出异常

优点:过程中写入缓存,不操作磁盘,最后一次写入磁盘,速度快

大文件写XSSF:

缺点:写数据时速度慢,非常耗内存,也可能会发生内存溢出,如:100万条时

优点:可以写入较大量数据,如:20万条。

大文件写SXSSF

它是一种基于流式处理的用户模型,适用于处理大量数据时,以减少内存消耗并提高性能。

与传统的基于用户模型的 API(如 HSSF)相比,SXSSF 可以将生成的数据直接写入磁盘,而不是先将数据全部加载到内存中,从而节省了内存开销。这使得 SXSSF 更适合处理大规模数据集或需要导出大型 Excel 文件的场景。

优点:可以写非常大的数据量,如100万条甚至更多,写数据速度快,占用更少内存少。

注意:过程中会产生临时文件,需要清理临时文件,默认由100条记录被保存在内存中,如果超过这数量,则前面的文件将会被写入临时文件。如果想自定义内存中数据的数量,可以使用

new SXSSFWorkbook(数量)

1.4 POI-Excel读

1.4.1 基本的读取  03 07 版本

package com.yang;import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;import java.io.FileInputStream;
import java.io.FileNotFoundException;/*** @author yzh* @date 2024-01-14*/public class ExcelReadTest {public static final String PATH = "E:\\ExcleTest\\";@Testpublic void readTest03() throws Exception {//1.获取文件流FileInputStream fileInputStream = new FileInputStream(PATH + "测试表.xls");//2..创建一个工作簿  使用excel能操作的工作簿都能操作Workbook workbook = new  HSSFWorkbook(fileInputStream);//3.获取表Sheet sheet = workbook.getSheetAt(0);//4.获取行Row row = sheet.getRow(0);//5.获取列Cell cell = row.getCell(1);//getStringCellValue获取字符串类型System.out.println(cell.getStringCellValue());fileInputStream.close();}@Testpublic void readTest07() throws Exception {//1.获取文件流FileInputStream fileInputStream = new FileInputStream(PATH + "测试表.xlsx");//2..创建一个工作簿  使用excel能操作的工作簿都能操作Workbook workbook = new XSSFWorkbook(fileInputStream);//3.获取表Sheet sheet = workbook.getSheetAt(0);//4.获取行Row row = sheet.getRow(0);//5.获取列Cell cell = row.getCell(1);//getStringCellValue获取字符串类型System.out.println(cell.getStringCellValue());fileInputStream.close();}
}

**注意获取值的类型**

1.4.2 读取不同的数据类型的值

    @Testpublic void cellTypeTest() throws Exception {//1.获取文件流FileInputStream fileInputStream = new FileInputStream(PATH + "权益导入模板.xlsx");//2..创建一个工作簿  使用excel能操作的工作簿都能操作Workbook workbook = new XSSFWorkbook(fileInputStream);Sheet sheet = workbook.getSheetAt(0);//读取标题内容Row rowTitle = sheet.getRow(0);if (rowTitle != null) {//读取列,得到一行有多少列有数据int cellCount = rowTitle.getPhysicalNumberOfCells();for (int cellNum = 0; cellNum < cellCount; cellNum++) {Cell cell = rowTitle.getCell(cellNum);if (cell != null) {String cellValue = cell.getStringCellValue();System.out.print(cellValue + "|");}}System.out.println();}//获取表中的内容int rowCount = sheet.getPhysicalNumberOfRows();for (int rowNum = 1; rowNum < rowCount; rowNum++) {Row rowData = sheet.getRow(rowNum);if (rowData != null) {//如果行不为空//读取列int cellCount = rowTitle.getPhysicalNumberOfCells();for (int cellNum = 0; cellNum < cellCount; cellNum++) {Cell cell = rowData.getCell(cellNum);//匹配列的数据类型if (cell != null) {CellType cellType = cell.getCellType();String cellValue = "";switch (cellType) {case STRING:System.out.println("STRING");cellValue = cell.getStringCellValue();break;case NUMERIC:System.out.println("NUMERIC");if (DateUtil.isCellDateFormatted(cell)) {System.out.println("日期");Date date = cell.getDateCellValue();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");cellValue = dateFormat.format(date);} else {System.out.println("普通数字");//防止数字过长cell.setCellType(CellType.STRING);//转换为字符串输出cellValue = cell.getStringCellValue();}break;case BOOLEAN:System.out.println("BOOLEAN");cellValue = String.valueOf(cell.getBooleanCellValue());break;case _NONE:System.out.println("_NONE");break;case ERROR:System.out.println("ERROR");break;}System.out.println(cellValue);}}}}fileInputStream.close();}//优化后@Testpublic void testReadExcel() throws Exception {String filePath = PATH + "权益导入模板.xlsx";try (InputStream is = new FileInputStream(filePath);Workbook workbook = new XSSFWorkbook(is)) {Sheet sheet = workbook.getSheetAt(0);// 创建自定义的DataFormatter对象DataFormatter dataFormatter = new DataFormatter(Locale.ENGLISH);// 读取标题行Row titleRow = sheet.getRow(0);List<String> titleList = readRowValues(titleRow, new DataFormatter());// 读取数据行List<List<String>> dataList = new ArrayList<>();for (int i = 1; i <= sheet.getLastRowNum(); i++) {Row dataRow = sheet.getRow(i);if (dataRow == null) {continue;}List<String> rowData = readRowValues(dataRow, new DataFormatter());dataList.add(rowData);}// 输出结果System.out.println("标题行:" + titleList);System.out.println("数据行:" + dataList);}}/*** 读取一行单元格的值** @param row          行对象* @param dataFormatter 数据格式化对象* @return 单元格值列表*/private List<String> readRowValues(Row row, DataFormatter dataFormatter) {List<String> values = new ArrayList<>();for (int i = 0; i < row.getLastCellNum(); i++) {Cell cell = row.getCell(i);String value = dataFormatter.formatCellValue(cell);// 判断是否为日期格式if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) {Date date = cell.getDateCellValue();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");value = dateFormat.format(date);}values.add(value);}return values;}

1.4.3 计算公式(了解即可)

    @Testpublic void testFormula() throws Exception {FileInputStream fileInputStream = new FileInputStream(PATH + "求和.xlsx");Workbook workbook = new XSSFWorkbook(fileInputStream);Sheet sheet = workbook.getSheetAt(0);Row row = sheet.getRow(5);Cell cell = row.getCell(0);//拿到计算公式FormulaEvaluator evaluator = new XSSFFormulaEvaluator((XSSFWorkbook)workbook);//输出单元格的内容CellType cellType = cell.getCellType();switch (cellType){case FORMULA:String formula = cell.getCellFormula();System.out.println(formula);//计算CellValue evaluate = evaluator.evaluate(cell);String result = evaluate.formatAsString();System.out.println(result);break;}}

2.EasyExcel

2.1EasyExcel简介

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模式,在上层做了模型转换的封装,让使用者更加简单方便

2.2使用写

2.2.1引入依赖

        <!--EasyExcel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.0-beta2</version></dependency><!-- FastJSON --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency>

2.2.2创建实体类

package com.yang.data;import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;import java.util.Date;/*** @author yzh* @date 2024-01-14*/
@Data
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;}

2.2.3测试

package com.yang;import com.alibaba.excel.EasyExcel;
import com.yang.data.DemoData;
import org.apache.commons.collections4.ListUtils;
import org.junit.Test;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @author yzh* @date 2024-01-14*/public class EasyExcelTest {public static final String PATH = "E:\\ExcleTest\\";private List<DemoData> data() {ArrayList<DemoData> list = new ArrayList<>();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}/*** 最简单的写* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 直接写即可*/@Testpublic void simpleWrite() {String fileName= PATH+"simpleWrite.xlsx";EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());}}

2.3 使用读

2.3.1创建DemoDataListener:【监听器】

package com.yang;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.yang.data.DemoData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.ArrayList;
import java.util.List;// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<DemoData> {private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);/*** 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;List<DemoData> list = new ArrayList<DemoData>();/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private DemoDAO demoDAO;public DemoDataListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数demoDAO = new DemoDAO();}/*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param demoDAO*/public DemoDataListener(DemoDAO demoDAO) {this.demoDAO = demoDAO;}/*** 这个每一条数据解析都会来调用** @param data*            one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context*/@Overridepublic void invoke(DemoData data, AnalysisContext context) {System.out.println(JSON.toJSONString(data));list.add(data);System.out.println(list);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();LOGGER.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {demoDAO.save(list);}
}

2.3.2持久层DemoDAO:

package com.yang;/*** @author yzh* @date 2024-01-14*/import com.yang.data.DemoData;import java.util.List;/*** 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。**/
public class DemoDAO {public void save(List<DemoData> list) {//持久化操作// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入}
}

2.3.3测试

package com.yang;import com.alibaba.excel.EasyExcel;
import com.yang.data.DemoData;
import org.apache.commons.collections4.ListUtils;
import org.junit.Test;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @author yzh* @date 2024-01-14*/public class EasyExcelTest {public static final String PATH = "E:\\ExcleTest\\";// 最简单的读@Testpublic void simpleRead() {String fileName = PATH+"simpleWrite.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}
}

参考文档:关于Easyexcel | Easy Excel

参考视频:【狂神说Java】POI及EasyExcel一小时搞定通俗易懂_哔哩哔哩_bilibili

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

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

相关文章

如何在CentOS下使用Docker部署Halo博客网站并结合内网穿透远程访问

文章目录 ⛳️ 推荐1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤&#xff1a;1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 ⛳️ 推荐 前些天发现了…

记一次 .NET某道闸收费系统 内存溢出分析

一&#xff1a;背景 1. 讲故事 前些天有位朋友找到我&#xff0c;说他的程序几天内存就要爆一次&#xff0c;不知道咋回事&#xff0c;找不出原因&#xff0c;让我帮忙看一下&#xff0c;这种问题分析dump是最简单粗暴了&#xff0c;拿到dump后接下来就是一顿分析。 二&…

Openwrt 下动态路由协议(quagga-OSPF)配置与验证

文章目录 前言网络拓扑静态路由方式动态路由方式Openwrt下 Quagga 安装Quagga 配置R1路由器zebra配置R1路由器ospf配置R2路由器zebra配置R2路由器ospf配置OSPF协议分析REF本文将在两台openwrt系统上安装配置quagga, 搭建一套完整环境,来验证OSPF动态路由的基本功能和实际效果,…

面经-redis缓存

什么是Redis Redis(Remote Dictionary Server)键只能为字符串&#xff0c;值&#xff1a;字符串、列表、集合、散列表、有序集合。Redis 用来做分布式锁。支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。 Redis为什么这么快 完全基于内存&#xff0c;数据结构简单…

深度学习记录--正则化(regularization)

什么是正则化&#xff1f; 正则化(regularization)是一种实用的减少方差(variance)的方法&#xff0c;也即避免过度拟合 几种正则化的方法 L2正则化 又被称为权重衰减(weight dacay) 在成本函数中加上正则项&#xff1a; 其中 由于在w的更新过程中会递减&#xff0c;即权…

2024年继续看好英伟达的两个理由

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 2023年是英伟达业务爆发式增长的一年 2023年可以说是英伟达成立近30年以来最好的一年。由于大语言模型带动的训练和推理算力需求的增加&#xff0c;导致市场对英伟达AI芯片(H100、A100等)和HGX平台的采购需求也出现了飙升…

鸿蒙Harmony-页面路由(router)详解

慢慢理解世界&#xff0c;慢慢更新自己&#xff0c;希望你的每一个昨天&#xff0c;今天&#xff0c;和明天都会很快乐&#xff0c;你知道的&#xff0c;先好起来的从来都不是生活&#xff0c;而是你自己 目录 一&#xff0c;定义 二&#xff0c;页面跳转 2.1使用router.pushU…

【Java】HttpServlet类中前后端交互三种方式(query string、form表单、JSON字符串)

在前后端的交互中&#xff0c;前端通过以下三种方式来与后端进行交互&#x1f31f; ✅query string ✅form表单 ✅JSON字符串 下面我们将书写这三种方式的后端代码并进行讲解 1、Query String QueryString即在url中写入键值对&#xff0c;一般用doGet方法进行交互 代码如下 …

2018年认证杯SPSSPRO杯数学建模D题(第一阶段)投篮的最佳出手点全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 对于投篮最佳出手点的探究 D题 投篮的最佳出手点 原题再现&#xff1a; 影响投篮命中率的因素不仅仅有出手角度、球感、出手速度&#xff0c;还有出手点的选择。规范的投篮动作包含两膝微屈、重心落在两脚掌上、下肢蹬地发力、身体随之向前上…

H3C校园网双出口配置

H3C校园网双出口配置 &#x1f3c6;荣誉认证&#xff1a;51CTO博客专家博主、TOP红人、明日之星&#xff1b;阿里云开发者社区专家博主、技术博主、星级博主。 &#x1f4bb;微信公众号&#xff1a;微笑的段嘉许 &#x1f4cc;本文由微笑的段嘉许原创&#xff01; &#x1f389…

服务器推送数据你还在用 WebSocket么?

当涉及到推送数据时,人们首先会想到 WebSocket。 的确,WebSocket 允许双向通信,可以自然地用于服务器到浏览器的消息推送。 然而,如果只需要单向的消息推送,HTTP 通过服务器发送的事件也有这种功能。 WebSocket 的通信过程如下: 首先,通过 HTTP 切换协议。服务器返回 101 状…

驾驭数字孪生:智慧水利的未来之路

一、数字孪生技术的原理与实践 随着科技的不断进步&#xff0c;数字孪生技术作为一项创新的技术应用&#xff0c;正在逐渐改变我们的生活和工作方式。特别是在工业领域&#xff0c;数字孪生技术被视为实现智能制造、提升生产效率和产品质量的重要手段。本章节将深入探讨数字孪…

k8s的对外服务--ingress

service作用体现在两个方面 1、集群内部 不断跟踪pod的变化&#xff0c;更新endpoint中的pod对象&#xff0c;基于pod的IP地址不断变化的一种服务发现机制 2、集群外部 类似负载均衡器&#xff0c;把流量ip端口&#xff0c;不涉及转发url&#xff08;http&#xff0c;https&a…

npm依赖库备份

常用命令 设置默认使用本地缓存安装Nodejs时会自动安装npm&#xff0c;但是局路径是C:\Users\Caffrey\AppData\Roaming\npm默认的缓存路径是C:\Users\Caffrey\AppData\Roaming\npm-cache&#xff1b;查看npm的prefix和cache路径配置信息设置路径 设置默认使用本地缓存 npm con…

本周五上海见 第二届证券基金行业先进计算技术大会暨2024低时延技术创新实践论坛(上海站)即将召开

低时延技术是证券基金期货领域业务系统的核心技术&#xff0c;是打造极速交易系统领先优势的关键&#xff0c;也是证券基金行业关注的前沿技术热点。 1月19日下午&#xff0c;第二届证券基金行业先进计算技术大会暨2024低时延技术创新实践论坛&#xff08;上海站&#xff09;即…

springmvc上传与下载

文件上传 结构图 导入依赖 <dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId…

MySQL之视图索引

学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept) 学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键 课程表&#xff1a;Course (Cno, Cname,) 课程号&#xff0c;课程名 Cno为主键 学生选课表&#xff1a;SC (Sno, Cno, Score)…

VSCODE使用CMAKE显示命令无法找到

背景&#xff1a;使用了code server&#xff0c;安装CMAKE和CMAKE TOOLS&#xff0c;但是通过ctrlshiftp打开命令面板&#xff0c;运行随便一个cmake指令&#xff0c;都出现了指令无法找到。具体为“命令"CMake: 配置"导致错误 (command ‘cmake.configure’ not fou…

GPT APP的开发步骤

开发一个GPT&#xff08;Generative Pre-trained Transformer&#xff09; Store&#xff08;存储&#xff09;涉及到使用预训练的语言模型&#xff08;例如GPT-3&#xff09;来生成和管理内容。以下是一般的步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&…

探索设计模式的魅力:抽象工厂模式的艺术

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;用于在不指定具体类的情况下创建一系列相关或相互依赖的对象。它提供了一个接口&#xff0c;用于创建一系列“家族”或相关依赖对象&#xff0c;而无需指定它们的具体类。 主要参…