当前位置: 首页 > article >正文

SpringBoot+tabula+pdfbox解析pdf中的段落和表格数据

一、前言

在日常业务需求中,往往会遇到解析pdf文件中的段落或者表格数据的需求。
常见的做法是使用 pdfbox 来做,但是它只能提取文本数据,没有我们在文件页面上面的那种结构化组织,文本通常是散乱的包含各种换行回车空格等格式,因而它适合做一些段落文本提取。
而 tabula 在 pdfbox 的基础上做了表格的特殊处理,能够直接读取到单元格中的内容,但是它处理的前提是表格必须常规完整边框的表格,只有部分边框或者无边框的这种结构化数据还是束手无策。
针对上述情况,笔者实现了有边框和无边框表格的数据读取并结构化,也支持段落文本提取。

二、功能实现

2.1 引入依赖

<!-- PDF解析,内含pdfbox -->
<dependency><groupId>technology.tabula</groupId><artifactId>tabula</artifactId><version>1.0.5</version>
</dependency>

2.2 完整边框表格

  • 支持多表格
  • 支持分页
  • 支持跳过标题行
  • 支持跳过标题前无关行
  • 支持生成字段
  • 返回完整集合数据
    在这里插入图片描述

2.2.1 代码实现

package com.qiangesoft.pdf.util;import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import technology.tabula.*;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** pdf工具类* ps:适合解析纯文本、解析表格数据** @author qiangesoft* @date 2025-05-28*/
@Slf4j
public class PdfUtil {public static void main(String[] args) throws FileNotFoundException {String txt = readTxtFromPdf("C:\\Users\\admin\\Desktop\\微信流水.pdf", null);System.out.println(txt);List<List<Map<String, String>>> dataGroupList = readTableDataFromPdf("C:\\Users\\admin\\Desktop\\微信流水.pdf", null, true);for (List<Map<String, String>> list : dataGroupList) {for (Map<String, String> map : list) {System.out.println(JSON.toJSONString(map));}}}/*** 解析pdf的文本数据** @param filePath 文件路径* @param password 文件密码* @return*/public static String readTxtFromPdf(String filePath, String password) throws FileNotFoundException {return readTxtFromPdf(new FileInputStream(filePath), password);}/*** 解析pdf的文本数据** @param inputStream 文件流* @param password 文件密码* @return*/public static String readTxtFromPdf(InputStream inputStream, String password) {String textContent = "";try (PDDocument document = PDDocument.load(inputStream, password)) {PDFTextStripper stripper = new PDFTextStripper();textContent = stripper.getText(document);} catch (IOException e) {e.printStackTrace();}return textContent;}/*** 解析pdf的表格数据** @param filePath 文件路径* @param password 文件密码* @param skipFirstRow 是否跳过表头行 【连续分页表格可能每页有表头】* @return*/public static List<List<Map<String, String>>> readTableDataFromPdf(String filePath, String password, boolean skipFirstRow) throws FileNotFoundException {return readTableDataFromPdf(new FileInputStream(filePath), password, skipFirstRow);}/*** 解析pdf的表格数据** @param inputStream 文件流* @param password 文件密码* @param skipFirstRow 是否跳过表头行* @return*/public static List<List<Map<String, String>>> readTableDataFromPdf(InputStream inputStream, String password, boolean skipFirstRow) {// 按照同一个表格分组List<List<Map<String, String>>> dataGroupList = new ArrayList<>();// 表格提取算法SpreadsheetExtractionAlgorithm algorithm = new SpreadsheetExtractionAlgorithm();try (PDDocument document = PDDocument.load(inputStream, password)) {ObjectExtractor extractor = new ObjectExtractor(document);PageIterator pi = extractor.extract();// 遍历页double x = 0;int tableIndex = 0;int tableHeadRowNum = 0;List<Table> tables = new ArrayList<>();List<String> fieldList = new ArrayList<>();while (pi.hasNext()) {Page page = pi.next();List<Table> tableList = algorithm.extract(page);// 遍历表格for (Table table : tableList) {if (tableIndex == 0) {tableHeadRowNum = getTableHeadRowNum(table, fieldList);tables.add(table);tableIndex++;} else {// 第一个 or x轴且列数相同为同一个表格if (new BigDecimal(table.getX()).subtract(new BigDecimal(x)).abs().compareTo(new BigDecimal("0.001")) <= 0&& fieldList.size() == table.getRows().get(0).size()) {tables.add(table);} else {List<Map<String, String>> dataList = convertTableToMap(tables, fieldList, tableHeadRowNum, skipFirstRow);dataGroupList.add(dataList);tables = new ArrayList<>();tables.add(table);tableIndex = 0;}}x = table.getX();}}// 最后一个特殊处理if (!tables.isEmpty()) {List<Map<String, String>> dataList = convertTableToMap(tables, fieldList, tableHeadRowNum, skipFirstRow);dataGroupList.add(dataList);}} catch (Exception e) {e.printStackTrace();}return dataGroupList;}/*** 获取字段并返回表格头的行** @param table 表格* @param fieldList 字段列表* @return*/private static int getTableHeadRowNum(Table table, List<String> fieldList) {// 获取表格头int headRowNum = 0;List<List<RectangularTextContainer>> rowList = table.getRows();for (int i = 0; i < rowList.size(); i++) {fieldList.clear();List<RectangularTextContainer> cellList = rowList.get(i);int k = 0;for (int j = 0; j < cellList.size(); j++) {RectangularTextContainer cell = cellList.get(j);if (cell instanceof Cell) {k++;fieldList.add("k" + k);}}if (fieldList.size() == cellList.size()) {headRowNum = i;break;}}return headRowNum;}/*** 将表格数据转为映射数据** @param tableList 表格列表* @param fieldList 字段列表* @param tableHeadRowNum 表格头行* @param skipFirstRow 是否跳过表头行* @return*/private static List<Map<String, String>> convertTableToMap(List<Table> tableList, List<String> fieldList, int tableHeadRowNum, boolean skipFirstRow) {List<Map<String, String>> dataList = new ArrayList<>();for (int i = 0; i < tableList.size(); i++) {// 表格所有行Table table = tableList.get(i);List<List<RectangularTextContainer>> rowList = table.getRows();// 遍历行for (int j = (i == 0 ? tableHeadRowNum + 1 : skipFirstRow ? 1 : 0); j < rowList.size(); j++) {List<RectangularTextContainer> cellList = rowList.get(j);Map<String, String> data = new HashMap<>();// 遍历列for (int m = 0; m < cellList.size(); m++) {RectangularTextContainer cell = cellList.get(m);// 去除换行符后设置值String text = cell.getText().replace("\r", "");data.put(fieldList.get(m), text);}dataList.add(data);}}return dataList;}/*** 读取指定文字中间的文本** @param txt 文本* @param startStr 开始字符串* @param endStr 结束字符串* @return*/public static String readTxtFormTxt(String txt, String startStr, String endStr) {int index1 = txt.indexOf(startStr);if (index1 == -1) {return null;}int index2 = txt.length();if (endStr != null) {index2 = txt.indexOf(endStr);if (index2 == -1) {index2 = txt.length();}}return txt.substring(index1 + startStr.length(), index2);}}

2.2.2 解析结果

在这里插入图片描述

2.3 无边框表格

  • 支持单表格
  • 支持分页
  • 支持跳过标题行
  • 支持生成字段
  • 返回完整集合数据
    在这里插入图片描述

2.3.1 代码实现

package com.qiangesoft.pdf.util;import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;import java.io.IOException;
import java.util.*;/*** pdf规则数据分析工具类* ps:分析处理PdfUtil解决不了的表格,没有格子** @author qiangesoft* @date 2025-05-28*/
public class PdfRuleDataUtil {public static void main(String[] args) throws IOException {String fileTxt = PdfUtil.readTxtFromPdf("C:\\Users\\admin\\Desktop\\流水文件\\中国建设银行.pdf", null);System.out.println(readTxt(fileTxt, "卡号/账号:", "客户名称:").trim());System.out.println(readTxt(fileTxt, "客户名称:", "起始日期:").trim());System.out.println(readTxt(fileTxt, "起始日期:", "结束日期:").trim());System.out.println(readTxt(fileTxt, "结束日期:", "序号").trim());List<Map<String, String>> dataList = readTableData(fileTxt, "序号 摘要 币别 钞汇 交易日期 交易金额 账户余额 交易地点/附言 对方账号与户名", "生成时间:");for (Map<String, String> map : dataList) {System.out.println(JSONObject.toJSONString(map));}}/*** 解析文本** @param fileTxt* @param startStr* @param endStr* @return*/public static String readTxt(String fileTxt, String startStr, String endStr) {return PdfUtil.readTxtFormTxt(fileTxt, startStr, endStr);}/*** 解析表格数据** @param fileTxt 文本数据* @param startStr 开始字符串 【一般为标题行,字段根据标题行定,***很重要***】* @param endStr 结束字符串 【结束标志,如果表格连续中间没有重复的标题行则直接使用表格末尾的结束标志即可,如果表格不连续每页都有标题行则使用每页的结束标志】* @return*/public static List<Map<String, String>> readTableData(String fileTxt, String startStr, String endStr) {int length = startStr.trim().split(" ").length;List<String> fieldList = new ArrayList<>();for (int i = 1; i <= length; i++) {fieldList.add("k" + i);}List<Map<String, String>> lists = new ArrayList<>();while (true) {String dataStr = readTxt(fileTxt, startStr, endStr);if (dataStr == null) {break;}List<Map<String, String>> pageLists = readDataFromTxt(dataStr, startStr, fieldList);fileTxt = fileTxt.substring(fileTxt.indexOf(endStr) + endStr.length());if (CollectionUtils.isEmpty(pageLists)) {break;} else {lists.addAll(pageLists);}}return lists;}/*** 解析pdf的文本数据* ps:通过换行符进行分割行,然后根据空格分割列【如果列中数据存在空格则无法解决】** @param dataStr 待解析的文本* @param tableHeadTxt 标题行文本* @param fieldList 字段列表* @return*/private static List<Map<String, String>> readDataFromTxt(String dataStr, String tableHeadTxt, List<String> fieldList) {List<Map<String, String>> dataList = new ArrayList<>();int cellNum = fieldList.size();// "\r\n" or "\n"String[] split = dataStr.split(System.lineSeparator());StringBuilder chargeStr = new StringBuilder();for (int a = 0; a < split.length; a++) {String itemStr = split[a];// 标题行跳过if (itemStr.contains(tableHeadTxt)) {continue;}String[] split1;if (!chargeStr.toString().isEmpty()) {// 上一行未处理【加上本行一起处理】chargeStr.append(itemStr);split1 = chargeStr.toString().split(" ");} else {split1 = itemStr.split(" ");}if (split1.length < cellNum) { // 不足列数// 拼接本行if (chargeStr.toString().isEmpty()) {chargeStr.append(itemStr);}// 最后一行特殊处理if (a == split.length - 1) {Map<String, String> dataMap = new HashMap<>();for (int i = 0; i < cellNum; i++) {if (i > split1.length - 1) {dataMap.put(fieldList.get(i), null);} else {dataMap.put(fieldList.get(i), split1[i]);}}dataList.add(dataMap);}} else if (split1.length > cellNum) { // 超过列数if (!chargeStr.toString().isEmpty()) {// 处理上一行String[] split2 = chargeStr.toString().replace(itemStr, "").split(" ");Map<String, String> dataMap = new HashMap<>();for (int i = 0; i < cellNum; i++) {if (i > split2.length - 1) {dataMap.put(fieldList.get(i), null);} else {dataMap.put(fieldList.get(i), split2[i]);}}dataList.add(dataMap);}// 处理本行chargeStr = new StringBuilder();String[] split3 = itemStr.split(" ");if (split3.length < cellNum) { // 本行不足列数// 拼接本行if (chargeStr.toString().isEmpty()) {chargeStr.append(itemStr);}// 最后一行特殊处理if (a == split.length - 1) {Map<String, String> dataMap = new HashMap<>();for (int i = 0; i < cellNum; i++) {if (i > split3.length - 1) {dataMap.put(fieldList.get(i), null);} else {dataMap.put(fieldList.get(i), split3[i]);}}dataList.add(dataMap);}} else { // 本行大于等于列数Map<String, String> dataMap = new HashMap<>();for (int i = 0; i < cellNum; i++) {if (i > split3.length - 1) {dataMap.put(fieldList.get(i), null);} else {dataMap.put(fieldList.get(i), split3[i]);}}dataList.add(dataMap);}} else { // 等于列数Map<String, String> dataMap = new HashMap<>();for (int i = 0; i < cellNum; i++) {dataMap.put(fieldList.get(i), split1[i]);}dataList.add(dataMap);chargeStr = new StringBuilder();}}return dataList;}}

2.3.2 解析结果

在这里插入图片描述

2.4 解析段落

在这里插入图片描述

2.4.1 代码实现

/*** 读取指定文字中间的文本** @param txt 文本* @param startStr 开始字符串* @param endStr 结束字符串* @return*/public static String readTxtFormTxt(String txt, String startStr, String endStr) {int index1 = txt.indexOf(startStr);if (index1 == -1) {return null;}int index2 = txt.length();if (endStr != null) {index2 = txt.indexOf(endStr);if (index2 == -1) {index2 = txt.length();}}return txt.substring(index1 + startStr.length(), index2);}

2.4.2 解析结果

在这里插入图片描述

三、源码仓库

码云:https://gitee.com/qiangesoft/boot-business/tree/master/boot-business-pdf

在这里插入图片描述

相关文章:

SpringBoot+tabula+pdfbox解析pdf中的段落和表格数据

一、前言 在日常业务需求中&#xff0c;往往会遇到解析pdf文件中的段落或者表格数据的需求。 常见的做法是使用 pdfbox 来做&#xff0c;但是它只能提取文本数据&#xff0c;没有我们在文件页面上面的那种结构化组织&#xff0c;文本通常是散乱的包含各种换行回车空格等格式&a…...

外包项目交付后还能怎么加固?我用 Ipa Guard 给 iOS IPA 增加了一层保障

在我们技术团队的日常工作中&#xff0c;接手外包开发者提交的 iOS 项目是一件常见的事。但你有没有遇到过这种情况&#xff1a;只交付了 IPA 文件&#xff0c;没有源码&#xff0c;也不方便追溯开发过程&#xff0c;但客户要求“上线前必须加一层安全防护”。 这是我们最近真…...

GitHub push失败解决办法-fatal: unable to access ‘https://github.com/xxx

问题描述&#xff1a; 问题解决&#xff1a; 1、首先查找自己电脑的代理地址和端口 windows教程如下&#xff1a; 1、搜索控制面板-打开Internet选项 2、点击局域网设置&#xff1a; 3、如图为地址和端口号 即可获得本机地址和端口号 2、根据上一步获得的本机地址和端口号为…...

USB MSC SCCI

&#x1f50d; ​数据包完整内容​ 0000 1b 00 10 09 22 8b 8b 9b ff ff 00 00 00 00 09 00 0010 00 02 00 02 00 02 03 1f 00 00 00 55 53 42 43 10 0020 09 22 8b 00 02 00 00 80 00 0a 28 00 00 00 00 00 0030 00 00 01 00 00 00 00 00 00 00 ⚙️ ​一、…...

解决Acrobat印前检查功能提示无法为用户配置文件问题

转载&#xff1a;https://zhuanlan.zhihu.com/p/18845570057 Acrobat整理页面时往往需要用到印前检查功能中的将页面缩放为A4&#xff0c;可以一键统一PDF文件所有页面大小&#xff0c;十分快捷。 不过&#xff0c;最新版本的Acrobat在安装时尽管勾选了可选功能-印前检查往往…...

华为OD最新机试真题-反转每对括号间的子串-OD统一考试(B卷)

题目描述: 给出一个字符串s(仅含有小写英文字母和括号)。 请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。注意,您的结果中不应包含任何括号。 示例1: 输入: s = “(abcd)” 输出: “dcba” 示例2:...

电商平台 API、数据抓取与爬虫技术的区别及优势分析

一、技术定义与核心原理 电商平台 API&#xff08;应用程序编程接口&#xff09; 作为平台官方提供的标准化数据交互通道&#xff0c;API 通过 HTTP 协议实现不同系统间的结构化数据传输。开发者需申请授权&#xff08;如 API 密钥&#xff09;&#xff0c;按照文档规范调用接口…...

领域驱动设计 (Domain-Driven Design, DDD)

文章目录 1. 引言1.1 什么是领域驱动设计1.2 为什么需要DDD1.3 DDD适用场景 2. DDD基础概念2.1 领域(Domain)2.2 模型(Model)与领域模型(Domain Model)2.3 通用语言(Ubiquitous Language) 3. 战略设计3.1 限界上下文(Bounded Context)3.2 上下文映射(Context Mapping)3.3 大型核…...

单卡4090部署Qwen3-32B-AWQ(4bit量化)-vllm

单卡4090部署Qwen3-32B-AWQ(4bit量化) 模型&#xff1a;Qwen3-32B-AWQ(4bit量化) 显卡&#xff1a;4090 1 张 python版本 python 3.12 推理框架“vllm 重要包的版本 vllm0.9.0创建GPU云主机 这里我使用的是优云智算平台的GPU&#xff0c;使用链接可以看下面的 https://blog.…...

漫画Android:Handler机制是怎么实现的?

线程之间通信会用到Handler&#xff0c;比如&#xff0c;在子线程中进行耗时的网络请求任务&#xff0c;子线程在获取到数据后&#xff0c;更新界面的时候就需要用到Handler&#xff1b; 子线程在获取到数据后&#xff0c;不直接去更新 界面&#xff0c;而是把数据通过一个消息…...

多部手机连接同一wifi的ip一样吗?如何更改ip

通常情况下&#xff0c;多部手机连接同一个WiFi时&#xff0c;它们的IP地址是各不相同的&#xff08;在局域网内&#xff09;。但是&#xff0c;从互联网&#xff08;外网&#xff09;的角度看&#xff0c;它们共享同一个公网IP地址。让我详细解释一下&#xff0c;并说明如何更…...

飞牛fnNAS的Docker应用之迅雷篇

目录 一、“迅雷”应用安装 二、启动迅雷 三、迅雷账号登录 四、修改“迅雷”下载保存路径 1、下载路径准备 2、停止“迅雷”Docker容器 3、修改存储位置 4、重新启动Docker容器 5、再次“启用”迅雷 五、测试 1、在PC上添加下载任务 2、手机上管理 3、手机添加下…...

C++中指针与引用的区别详解:从原理到实战

C中指针与引用的区别详解&#xff1a;从原理到实战 1. 引言&#xff1a;指针与引用的重要性 在C编程中&#xff0c;指针和引用是两个极其重要的概念&#xff0c;也是许多初学者容易混淆的地方。作为C的核心特性&#xff0c;它们直接操作内存地址&#xff0c;提供了对内存的直…...

SQLMesh 用户定义变量详解:从全局到局部的全方位配置指南

SQLMesh 提供了灵活的多层级变量系统&#xff0c;支持从全局配置到模型局部作用域的变量定义。本文将详细介绍 SQLMesh 的四类用户定义变量&#xff08;global、gateway、blueprint 和 local&#xff09;以及宏函数的使用方法。 一、变量类型概述 SQLMesh 支持四种用户定义变量…...

inviteflood:基于 UDP 的 SIP/SDP 洪水攻击工具!全参数详细教程!Kali Linux教程!

简介 一种通过 UDP/IP 执行 SIP/SDP INVITE 消息泛洪的工具。该工具已在 Linux Red Hat Fedora Core 4 平台&#xff08;奔腾 IV&#xff0c;2.5 GHz&#xff09;上测试&#xff0c;但预计该工具可在各种 Linux 发行版上成功构建和执行。 inviteflood 是一款专注于 SIP 协议攻…...

软件工程:关于招标合同履行阶段变更的法律分析

关于招标合同履行阶段建设内容变更的法律分析 一、基本原则 合同严守原则 根据《民法典》第465条&#xff0c;依法成立的合同受法律保护&#xff0c;原则上双方应严格按照约定履行。招标合同作为特殊类型的民事合同&#xff0c;其履行过程应当遵循更为严格的变更规则。 禁止…...

mysql一主多从 k8s部署实际案例

一、Kubernetes配置&#xff08;MySQL主从集群&#xff09; 主库StatefulSet配置&#xff08;master-mysql.yaml&#xff09;&#xff1a; apiVersion: apps/v1 kind: StatefulSet metadata:name: mysql-master spec:serviceName: "mysql-master"replicas: 1select…...

Visual Studio 2022 设置自动换行

Visual Studio 2022 设置自动换行 一、在 Visual Studio 菜单栏上&#xff0c;选择 工具>选项二、选择“文本编辑器”>“所有语言”>“常规” 全局设置此选项。 一、在 Visual Studio 菜单栏上&#xff0c;选择 工具>选项 二、选择“文本编辑器”>“所有语言”&…...

沉浸式 “飞进” 鸟巢:虚拟旅游新体验​

&#xff08;一&#xff09;全方位视角探秘​ 开启鸟巢虚拟旅游&#xff0c;借助 VR 技术&#xff0c;能从任意角度欣赏其外观。高空俯瞰&#xff0c;独特的钢结构如精美编织画卷&#xff0c;钢梁交织&#xff0c;阳光下闪耀银光&#xff0c;与绿树、蓝天相衬。拉近镜头&#x…...

Ubuntu 下同名文件替换后编译链接到旧内容的现象分析

Ubuntu 下同名文件替换后编译链接到旧内容的现象分析 在使用 Ubuntu 操作系统编译程序时&#xff0c;常常会遇到一个问题&#xff1a;当我们替换同名文件内容后&#xff0c;若不改变当前命令行目录&#xff0c;再次编译时&#xff0c;系统实际编译的仍是被覆盖前的旧文件内容。…...

【Linux网络篇】:简单的TCP网络程序编写以及相关内容的扩展

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;Linux篇–CSDN博客 文章目录 一.简单的TCP网络程序相关接口代码实现服务器单进程版服务器多…...

22.代理模式:思考与解读

原文地址:代理模式&#xff1a;思考与解读 更多内容请关注&#xff1a;深入思考与解读设计模式 引言 在软件开发中&#xff0c;尤其是当对象的访问需要控制时&#xff0c;你是否遇到过这样的问题&#xff1a;某些操作或对象可能需要进行额外的检查、优化或延迟加载&#xff…...

Scratch节日 | 粽子收集

端午节怎么过&#xff1f;当然是收粽子啦&#xff01;这款 粽子收集 小游戏&#xff0c;让你一秒沉浸节日氛围&#xff0c;轻松收集粽子&#xff0c;收获满满快乐&#xff01; &#x1f3ae; 玩法介绍f 开始游戏&#xff1a;点击开始按钮&#xff0c;游戏正式开始&#xff01;…...

stl三角面元文件转颗粒VTK文件

效果展示&#xff1a; import os import sys import json import argparse import numpy as np import pandas as pd import open3d as o3d from glob import globPARTICLE_RADIUS 0.025def stl_to_particles(objpath, radiusNone):if radius is None:radius PARTICLE_RADIU…...

Java String的使用续 -- StringBuilder类和StringBuffer

文章目录 字符串的不可变性StringBuilder和StringBuffer函数使用 字符串的不可变性 字符串不可变是因为有private修饰&#xff0c;只能在类的内部使用不可以在类外使用&#xff0c;因此使用时是不可以修改字符串的 public class test {public static void main(String[] args…...

Android学习之定时任务

Android定时任务的实现方式 在Android开发中&#xff0c;定时任务主要可以通过以下两类方式实现&#xff1a; Android系统组件 Handler消息机制&#xff1a;通过Handler.postDelayed()实现延时任务&#xff0c;适合简单UI线程操作AlarmManager&#xff1a;系统级定时服务&…...

WEB安全--RCE--webshell HIDS bypass4

继WEB安全--RCE--webshell HIDS bypass3的补充&#xff1a; 十三、时间开关 webshell&#xff1a; <?php ini_set("display_errors",1); function foo($test, $bar FSYSTEM) {echo $test . $bar; } $function new ReflectionFunction(foo); $q new ParseEr…...

基于python+Django+Mysql的校园二手交易市场

文章目录 基于pythonDjangoMysql的校园二手交易市场运行步骤系统设计功能设计任务目标用户特点参与者列表基本要求功能模块图 数据库设计会员用户信息表&#xff08;user_userinfo&#xff09;商品信息表&#xff08;goods_goodsinfo&#xff09;管理员用户信息表&#xff08;a…...

从零打造算法题刷题助手:Agent搭建保姆级攻略

我用Trae 做了一个有意思的Agent 「大厂机试助手」。 点击 https://s.trae.com.cn/a/d2a596 立即复刻&#xff0c;一起来玩吧&#xff01; Agent 简介 Agent名称为大厂机试助手&#xff0c;主要功能有以下三点。 解题&#xff1a; 根据用户给出的题目给出具体的解题思路引导做…...

Oracle 12c新增的数字转换验证VALIDATE_CONVERSION函数

Oracle 12c新增的数字转换验证函数 一、VALIDATE_CONVERSION函数&#xff08;12c R2新增&#xff09; Oracle 12c Release 2引入了原生验证函数&#xff0c;可直接判断字符串能否转换为指定类型&#xff1a; SELECT VALIDATE_CONVERSION(123.45 AS NUMBER) FROM dual; -- 返…...