Java 兼容读取WPS和Office图片,结合EasyExcel读取单元格信息
在Java开发中,处理Excel文件中的图片(包括浮动图片和嵌入图片)是一个常见的需求。本文将介绍如何使用EasyExcel和Apache POI库来读取Excel文件中的图片,并将其与数据进行关联。
1. 引言
在许多应用场景中,Excel文件不仅包含数据,还可能嵌入了图片。为了有效地提取这些图片并与数据关联,我们需要使用合适的库和方法。本文将详细介绍如何实现这一过程。
浮动图片

内嵌图片

pom
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version>
</dependency>
<dependency><groupId>org.jdom</groupId><artifactId>jdom2</artifactId><version>2.0.6</version>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version>
</dependency>
java代码
public class MySAXParserHandler extends DefaultHandler {String value = null;List<String> rows = new ArrayList<>();int rowIndex = 0;public List<String> getRows() {return rows;}/*** 用来标识解析开始*/@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubsuper.startDocument();// System.out.println("SAX解析开始");}/*** 用来标识解析结束*/@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();// System.out.println("SAX解析结束");}/*** 解析xml元素*/@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {// 调用DefaultHandler类的startElement方法super.startElement(uri, localName, qName, attributes);if (qName.equals("row")) {value = "";}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {//调用DefaultHandler类的endElement方法super.endElement(uri, localName, qName);if (qName.equals("row")) {if (value != null && value.contains("DISPIMG")) {value = value.substring(value.lastIndexOf("DISPIMG(")).replace("DISPIMG(\"", "");value = value.substring(0, value.indexOf("\""));rows.add(rowIndex, value);} else {rows.add(rowIndex, null);}rowIndex++;value = "";}}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {super.characters(ch, start, length);value += new String(ch, start, length);}
}
@Data
public class BatchSupplierGoodImportForm {private Integer supplierId;private String supplierCode;@Data@NoArgsConstructor@AllArgsConstructorpublic static class GoodItem {@ExcelProperty(value = "产品名称")private String productName;@ExcelImageProperty(value = {"imageUrl"}, index = 2)@ExcelProperty(value = "图片", converter = ExcelUrlImageConverter.class)private String imageUrl;@ExcelProperty(value = "品牌")private String supplierBrand;@ExcelProperty(value = "规格")private String skuDesc;@ExcelProperty(value = "集采价")private String groupPurchasePrice;@ExcelProperty(value = "卖点")private String sellPoint;}
}
public class ExcelImageExtractor2 {public static void main(String[] args) throws Exception {// 测试文件路径File xlsFile = new File("E:\\WeChat Files\\xxx\\FileStorage\\File\\2025-01\\测试.xls");File xlsxFile = new File("E:\\WeChat Files\\xxx\\FileStorage\\File\\2025-01\\测试.xlsx");String fileDir = "E:\\WeChat Files\\xxx\\FileStorage\\File\\2025-01";// 读取 .xls 文件中的浮动图片System.out.println("读取 .xls 文件中的浮动图片...");//readXlsImages(xlsFile, fileDir);// 读取 .xlsx 文件中的浮动图片System.out.println("读取 .xlsx 文件中的浮动图片...");//readXlsxImages(xlsxFile, fileDir);// 读取 .xlsx 文件中的嵌入图片System.out.println("读取 .xlsx 文件中的嵌入图片...");//readXlsxEmbeddedImages2(xlsxFile, fileDir);System.out.println("读取 ");importExcelSpuItem(xlsxFile, fileDir);}@SneakyThrowspublic static void importExcelSpuItem(File originalFile, String fileDir) {try {// 将上传的文件缓存到内存中,方便多次读取byte[] fileBytes = FileUtils.readFileToByteArray(originalFile);// 第一步:动态读取 Excel 文件的表头和所有数据List<Map<Integer, String>> headerList = new ArrayList<>();List<Map<Integer, String>> rawDataList = new ArrayList<>();List<BatchSupplierGoodImportForm.GoodItem> goodItemExcelInputs = new ArrayList<>();EasyExcel.read(new ByteArrayInputStream(fileBytes)).registerReadListener(new AnalysisEventListener<Map<Integer, String>>() {@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {headerList.add(headMap); // 捕获表头信息}@Overridepublic void invoke(Map<Integer, String> data, AnalysisContext context) {// 检查是否为空行if (isEmptyRow(data)) {return; // 跳过空行}rawDataList.add(data); // 捕获每行数据}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 不需要额外操作}}).sheet().doRead();// 检查是否成功读取到表头if (headerList.isEmpty()) {throw new RuntimeException("Excel 文件中没有表头");}// 第二步:读取 Excel 文件中的图片Map<Integer, String> imagePathMap = new HashMap<>(); // 行号 -> 图片路径readXlsxImages(originalFile, fileDir, imagePathMap);readXlsxEmbeddedImages2(originalFile, fileDir, imagePathMap);// 第三步:将图片与每行数据对应for (int i = 0; i < rawDataList.size(); i++) {Map<Integer, String> rowData = rawDataList.get(i);BatchSupplierGoodImportForm.GoodItem item = new BatchSupplierGoodImportForm.GoodItem();// 提取每列数据item.setProductName(rowData.get(0));item.setImageUrl(imagePathMap.getOrDefault(i + 1, null)); // 根据行号获取图片路径item.setSupplierBrand(rowData.get(2));item.setSkuDesc(rowData.get(3));item.setGroupPurchasePrice(rowData.get(4));item.setSellPoint(rowData.get(5));// 添加到列表goodItemExcelInputs.add(item);// 输出每行数据的文本内容和图片路径//System.out.println("行号: " + i);//System.out.println("数据: " + rowData);//System.out.println("图片路径: " + imagePathMap.getOrDefault(i, "无图片"));}System.out.println(goodItemExcelInputs);} catch (IOException e) {throw new RuntimeException("文件读取失败", e);}}/*** 判断是否为空行*/private static boolean isEmptyRow(Map<Integer, String> data) {for (String value : data.values()) {if (StringUtils.isNotBlank(value)) {return false;}}return true;}// 读取 .xls 文件中的浮动图片public static void readXlsImages(File file, String fileDir) throws Exception {HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(file));for (Sheet sheet : workbook) {HSSFSheet hssSheet = (HSSFSheet) sheet;HSSFPatriarch drawingPatriarch = hssSheet.getDrawingPatriarch();if (drawingPatriarch != null) {List<HSSFShape> shapes = drawingPatriarch.getChildren();for (HSSFShape shape : shapes) {if (shape instanceof HSSFPicture) {HSSFPicture pic = (HSSFPicture) shape;HSSFPictureData picData = pic.getPictureData();HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();String key = anchor.getRow1() + "行," + anchor.getCol1() + "列";byte[] data = picData.getData();String suffix = picData.suggestFileExtension();File dir = new File(fileDir);if (!dir.exists()) dir.mkdirs();FileUtils.writeByteArrayToFile(new File(dir, key + "." + suffix), data);}}}}workbook.close();}// 读取 .xlsx 文件中的浮动图片public static void readXlsxImages(File file, String fileDir, Map<Integer, String> imagePathMap) throws Exception {XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(file));for (Sheet sheet : workbook) {XSSFSheet xssSheet = (XSSFSheet) sheet;XSSFDrawing drawing = xssSheet.getDrawingPatriarch();if (drawing != null) {List<XSSFShape> shapes = drawing.getShapes();for (XSSFShape shape : shapes) {if (shape instanceof XSSFPicture) {XSSFPicture pic = (XSSFPicture) shape;XSSFPictureData picData = pic.getPictureData();XSSFClientAnchor anchor = (XSSFClientAnchor) shape.getAnchor();String key = anchor.getRow1() + "行," + anchor.getCol1() + "列";byte[] data = picData.getData();String suffix = picData.suggestFileExtension();File dir = new File(fileDir);if (!dir.exists()) dir.mkdirs();FileUtils.writeByteArrayToFile(new File(dir, key + "." + suffix), data);imagePathMap.put(anchor.getRow1(), key + "." + suffix);}}}}workbook.close();}// 读取 .xlsx 文件中的嵌入图片public static void readXlsxEmbeddedImages2(File file, String fileDir, Map<Integer, String> imagePathMap) throws Exception {OPCPackage opcPackage = OPCPackage.open(new FileInputStream(file));List<PackagePart> parts = opcPackage.getParts();Map<Integer, List<PackagePart>> picturePath = getEmbedPictures(parts);for (Integer sheetIndex : picturePath.keySet()) {List<PackagePart> rows = picturePath.get(sheetIndex);for (int i = 0; i < rows.size(); i++) {PackagePart part = rows.get(i);if (part != null) {InputStream imgIs = part.getInputStream();String name = part.getPartName().getName();// 从 XML 文件中解析行和列信息String cellPosition = getCellPosition(sheetIndex, i, parts);// 保存图片到本地File dir = new File(fileDir);if (!dir.exists()) dir.mkdirs();FileUtils.copyInputStreamToFile(imgIs, new File(dir, "工作表" + sheetIndex + "_" + cellPosition + "_" + name.substring(name.lastIndexOf("/") + 1)));imagePathMap.put(i, cellPosition + "_" + name.substring(name.lastIndexOf("/") + 1));}}}opcPackage.close();}/*** 获取图片所在的单元格位置(行和列)。** @param sheetIndex 工作表索引* @param imageIndex 图片索引* @param parts 压缩包中的所有部分* @return 单元格位置(如 "5行_3列")*/private static String getCellPosition(int sheetIndex, int imageIndex, List<PackagePart> parts) throws Exception {// 解析 `/xl/worksheets/sheet*.xml` 文件,获取行和列信息for (PackagePart part : parts) {String name = part.getPartName().getName();if (name.equals("/xl/worksheets/sheet" + (sheetIndex + 1) + ".xml")) {SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();MySAXParserHandler handler = new MySAXParserHandler();parser.parse(part.getInputStream(), handler);// 获取图片对应的行和列信息List<String> rows = handler.getRows();if (imageIndex < rows.size()) {return rows.get(imageIndex); // 返回行和列信息}}}return "未知行_未知列"; // 如果未找到,返回默认值}@SneakyThrowsprivate static Map<Integer, List<PackagePart>> getEmbedPictures(List<PackagePart> parts) {Map<String, Set<String>> mapImg = new HashMap<>();Map<String, String> mapImgPath = new HashMap<>();Map<Integer, List<String>> dataMap = new HashMap<>();for (PackagePart part : parts) {
// System.out.println(part.getPartName());PackagePartName partName = part.getPartName();String name = partName.getName();if ("/xl/cellimages.xml".equals(name)) {SAXBuilder builder = new SAXBuilder();// 获取文档Document doc = builder.build(part.getInputStream());// 获取根节点Element root = doc.getRootElement();List<Element> cellImageList = root.getChildren();for (Element imgEle : cellImageList) {Element xdrPic = imgEle.getChildren().get(0);Element xdrNvPicPr = xdrPic.getChildren().get(0);Element xdrBlipFill = xdrPic.getChildren().get(1);Element aBlip = xdrBlipFill.getChildren().get(0);Attribute attr = aBlip.getAttributes().get(0);String imgId = xdrNvPicPr.getChildren().get(0).getAttributeValue("name");String id = attr.getValue();
// if (id.equals("rId12")) {
// System.out.println(attr.getValue() + "\t" + imgId);
// }if (mapImg.containsKey(id)) {mapImg.get(id).add(imgId);} else {Set<String> set = new HashSet<>();set.add(imgId);mapImg.put(id, set);}}}if ("/xl/_rels/cellimages.xml.rels".equals(name)) {SAXBuilder builder = new SAXBuilder();// 获取文档Document doc = builder.build(part.getInputStream());// 获取根节点Element root = doc.getRootElement();List<Element> relationshipList = root.getChildren();/*<Relationship Id="rId999" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1000.jpeg"/>*/for (Element relationship : relationshipList) {String id = relationship.getAttributeValue("Id");String target = relationship.getAttributeValue("Target");mapImgPath.put(id, target);
// if (id.equals("rId12")) {
// System.out.println(id + "\t" + target);
// }}}if (name.contains("/xl/worksheets/sheet")) {
// SAXBuilder builder = new SAXBuilder();// 获取文档String sheetNoStr = name.replace("/xl/worksheets/sheet", "").replace(".xml", "");Integer sheetNo = Integer.valueOf(sheetNoStr) - 1;// 步骤1:创建SAXParserFactory实例SAXParserFactory factory = SAXParserFactory.newInstance();// 步骤2:创建SAXParser实例SAXParser parser = factory.newSAXParser();MySAXParserHandler handler = new MySAXParserHandler();parser.parse(part.getInputStream(), handler);List<String> rows = handler.getRows();dataMap.put(sheetNo, rows);}}// for (Integer sheetNo : dataMap.keySet()) {
// System.out.println(sheetNo + "\t" + dataMap.get(sheetNo).size());
// }Map<String, String> imgMap = new HashMap<>();for (String id : mapImg.keySet()) {Set<String> imgIds = mapImg.get(id);String path = mapImgPath.get(id);for (String imgId : imgIds) {imgMap.put(imgId, path);}}for (Integer key : dataMap.keySet()) {List<String> rows = dataMap.get(key);for (int i = 0; i < rows.size(); i++) {String imgId = rows.get(i);if (imgMap.containsKey(imgId)) {rows.set(i, imgMap.get(imgId));}}}Map<Integer, List<PackagePart>> map = new HashMap<>();for (Integer key : dataMap.keySet()) {List<PackagePart> list = new ArrayList<>();map.put(key, list);List<String> pathList = dataMap.get(key);for (int i = 0; i < pathList.size(); i++) {list.add(i, null);String path = pathList.get(i);if (StringUtils.isNotEmpty(path)) {for (PackagePart part : parts) {PackagePartName partName = part.getPartName();String name = partName.getName();// /xl/media/image373.jpeg = media/image702.jpegif (name.contains(path)) {list.set(i, part);break;}}}}}return map;}
}
参考链接:https://blog.csdn.net/qq_23123177/article/details/133638391
相关文章:
Java 兼容读取WPS和Office图片,结合EasyExcel读取单元格信息
在Java开发中,处理Excel文件中的图片(包括浮动图片和嵌入图片)是一个常见的需求。本文将介绍如何使用EasyExcel和Apache POI库来读取Excel文件中的图片,并将其与数据进行关联。 1. 引言 在许多应用场景中,Excel文件不…...
电脑硬盘系统迁移及问题处理
一、系统迁移准备 1、确认你的电脑主板是否支持安装两块硬盘,如电脑主板有多个M2硬盘接口,我们将新硬盘安装到主板上,原来的老硬盘安装在第二个接口上,主板只有一个M2接口的话可以使用移动硬盘盒。 2、新硬盘安装好后,我们进入原来的系统,在 此电脑–右键–管理–磁盘管…...
网关 + Nacos配置管理
网关 网关:就是网络的关口,负责请求的路由、转发、身份校验。 网关路由 新建网关模块gateway引入相关依赖 <!--网关--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter…...
《Spring Framework实战》6:核心技术 4.1.IoC 容器
欢迎观看《Spring Framework实战》视频教程 本章介绍 Spring 的控制反转 (IoC) 容器。 本部分摘要 Spring IoC 容器和 Bean 简介 容器概述 Bean 概述 依赖 Bean 作用域 自定义 Bean 的性质 Bean 定义继承 容器扩展点 基于注解的容器配置 Clas…...
ModuleNotFoundError: No module named ‘audioop‘
问题 ModuleNotFoundError: No module named pyaudioop ModuleNotFoundError: No module named audioop解决方案 安装库 pip3 install audioop-lts...
STM32-笔记38-I2C-oled实验
一、什么是I2C? I2C总线,全称Inter-Integrated Circuit(互连集成电路),是一种由Philips(现NXP半导体)公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C&…...
人大金仓实现主键自增.
使用数据库中自带的参数类型 serial 类型(相当于创建一个INT列), 或者bigserial(相当于创建一个BIGINT列. 示例sql: CREATE TABLE ord(id SERIAL,ord_no INT NOT NULL,ord_name VARCHAR(32),CONSTRAINT "ord_PKEY" PRIMARY KEY ("id"));插入时指定自增值…...
h264之多视点mvc编码及解码过程(JMVC平台举例)
h264标准参考平台JMVC是针对MVC标准的,JMVC支持多视点编码、合流、多视点解码操作。可以利用JMVC生成h264 mvc码流和解码。 JMVC的下载地址是:jvet / JMVC GitLabH.264/AVC multi-view coding (MVC) extension JMVC reference softwarehttps://vcgit.hh…...
小程序学习08—— 系统参数获取和navBar组件样式动态设置
一 系统信息的概念 uni-app提供了异步(uni.getSystemInfo)和同步(uni.getSystemInfoSync)的2个API获取系统信息。 success 返回参数说明: 参数分类说明statusBarHeight手机状态栏的高度system操作系统名称及版本。。。 二 自定义navbar 2.1 获取系统参数 代码展示…...
数据库环境安装(day1)
网址:MySQL 下载(环境准备): (2-5点击此处,然后选择合适的版本) 1.linux在线YUM仓库 下载/安装: wget https://repo.mysql.com//mysql84-community-release-el9-1.noarch.rpm rpm -i https://r…...
网络安全-web渗透环境搭建-BWAPP(基础篇)
01--所需系统环境: 虚拟主机系统部署(vmware,虚拟主机创建、虚拟主机网络配置(桥接,便于网络中多个主机都能访问虚拟主机)、虚拟软件功能,快照、克隆、镜像文件加载,ova文件制作&am…...
当算法遇到线性代数(三):实对称矩阵
实对称矩阵的理论与应用 线性代数系列相关文章(置顶) 1.当算法遇到线性代数(一):二次型和矩阵正定的意义 2.当算法遇到线性代数(二):矩阵特征值的意义 3.当算法遇到线性代数&#x…...
WayLand的架构和协议
WayLand的架构和协议 1. Wayland简介 1.1 Wayland是啥?为啥它这么重要? 嘿,你知道吗?有时候咱们用电脑的时候,是不是觉得图形界面有点慢、有点卡?那是因为我们还在用一个叫X Window System (X11)的老伙计…...
STM32学习(十)
I2C模块内部结构 I2C(Inter-Integrated Circuit)模块是一种由Philips公司开发的二线式串行总线协议,用于短距离通信,允许多个设备共享相同的总线。 硬件连接简单:I2C通信仅需要两条总线,即SCL&…...
进阶篇-Day17:JAVA的日志、枚举、类加载器、反射等介绍】
目录 1、日志1.1 日志概念1.2 日志框架(1) Logback框架:(2)配置文件介绍: 2、枚举3、类加载器3.1 类加载器的介绍3.2 类加载器的加载过程:加载、链接、初始化3.3 类加载器的分类3.4 双亲委派模式…...
Java设计模式 —— 【行为型模式】责任链模式(Chain-of-responsibility Pattern) 详解
文章目录 模式介绍优缺点适用场景模式结构案例实现 模式介绍 责任链模式又名职责链模式,它是一种对象行为的设计模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链&…...
C++和Python中负数取余结果的区别
C中的负数取余规则(取模%)规则 在C中,取余运算( % )的结果符号与被除数相同。从数学定义角度看,C遵循的是尽量让商向零取整的规则。例如计算 -7/3,商是 -2 (向零取整)&a…...
rust学习——环境搭建
rust安装:https://kaisery.github.io/trpl-zh-cn/ch01-01-installation.html 1、vscode装插件: toml语法支持 依赖管理 rust语法支持 2、创建demo 3、查看目录 4、执行文件的几种方式: rust安装:https://www.rust-lang.org/z…...
Linux系统中解决端口占用问题
在日常的 Linux 系统管理和开发过程中,端口占用是一个常见且令人头疼的问题。无论是部署新服务、调试应用程序,还是进行系统维护,遇到端口被占用都可能导致服务无法正常启动或运行。本文将详细介绍在 Linux 系统中如何识别和解决端口占用问题…...
现代软件架构设计:14个质量属性的定义、权衡与最佳实践
1. 引言 1.1 技术架构的重要性 技术架构是指导软件系统设计和开发的核心,它定义了系统的高层结构及关键技术选型。一个优秀的技术架构可以提高开发效率、系统稳定性和扩展能力,确保项目成功落地。面对复杂业务场景,技术架构的设计至关重要&…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
