PDF文件替换内容(电子签章),依赖免费pdfbox
首先提前准备,压入如下依赖
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.16</version>
</dependency>
正文开始
创建:
CoordinateDTO 坐标bean,用来存替换文字的坐标位置
PdfBoxKeyWordPosition 工具类,解析pdf文件,获取关键字坐标
ReportUtils 工具类,替换文件内容,可用于电子签章
源码如下:
(注:源码中的package...和import...需要修改为项目实际位置)
CoordinateDTO.java
/*** @FileName: CoordinateDTO.java* @creator yongzhizean* @date 2023年2月17日 下午5:16:52* @editor* @Description:* @version V1.0*/
package ...包位置;import lombok.Data;/*** @ClassName: CoordinateDTO * @Description: 坐标* @author yongzhizean* @date 2023年2月17日 下午5:16:52* @version V1.0*/
@Data
public class CoordinateDTO {/*** 关键字在PDF中的X坐标*/private Float x;/*** 关键字在PDF中的Y坐标*/private Float y;/*** 关键字在PDF中的页码*/private Integer pageNum;/*** 关键字在PDF中的显示出来的长度*/private Float length;
}
PdfBoxKeyWordPosition.java
/*** @FileName: PdfBoxKeyWordPosition.java* @creator yongzhizean* @date 2023年2月17日 下午5:16:52* @editor* @Description:* @version V1.0*/
package ...自己包位置;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;import ...CoordinateDTO位置;import lombok.extern.slf4j.Slf4j;import java.io.*;
import java.util.ArrayList;
import java.util.List;/*** @ClassName: PdfBoxKeyWordPosition* @Description: 解析pdf文件,获取关键字坐标* @author yongzhizean* @date 2023年2月17日 下午5:16:52* @version V1.0*/
@Slf4j
public class PdfBoxKeyWordPosition extends PDFTextStripper {/*** 关键字字符数组*/private char[] key;/*** 关键字字符数组*/private boolean flag;/*** 坐标集合*/private List<CoordinateDTO> coordinates = new ArrayList<CoordinateDTO>();/*** 当前页坐标集合*/private List<CoordinateDTO> pageList = new ArrayList<CoordinateDTO>();/*** 使用字符流* * @param keyWords* @param document* @param flag* @throws IOException*/public PdfBoxKeyWordPosition(String keyWords, PDDocument document, boolean flag) throws IOException {super();super.setSortByPosition(true);this.document = document;this.flag = flag;char[] key = new char[keyWords.length()];for (int i = 0; i < keyWords.length(); i++) {key[i] = keyWords.charAt(i);}this.key = key;}/*** * 获取坐标信息* @date 2023年2月17日 下午5:22:34* @author yongzhizean* @return* @return List<CoordinateDTO>*/public List<CoordinateDTO> getCoordinate() {try {int pages = document.getNumberOfPages();for (int i = 1; i <= pages; i++) {super.setSortByPosition(true);super.setStartPage(i);super.setEndPage(i);Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());super.writeText(document, dummy);for (CoordinateDTO li : pageList) {li.setPageNum(i);}coordinates.addAll(pageList);pageList.clear();}} catch (Exception e) {log.error("获取pdf关键字坐标失败:{}", e);} finally {pageList.clear();if (flag) {try {if (document != null) {document.close();}} catch (IOException e) {log.error("关闭文件失败:{}", e);}} else {log.info("不关闭文件");}}return coordinates;}/*** 获取坐标信息*/@Overrideprotected void writeString(String string, List<TextPosition> textPositions) throws IOException {for (int i = 0; i < textPositions.size(); i++) {String str = textPositions.get(i).getUnicode();// 找到 key 中第一位所在位置if (str.equals(String.valueOf(key[0]))) {int count = 0;for (int j = 0; j < key.length; j++) {String s = "";try {s = textPositions.get(i + j).getUnicode();} catch (Exception e) {s = "";}// 判断key 中每一位是否和文本中顺序对应,一旦不等说明 关键字与本段落不等,则停止本次循环if (s.equals(String.valueOf(key[j]))) {count++;} else if (count > 0) {break;}}// 判断 key 中字 在文本是否连续,是则获取坐标if (count == key.length) {CoordinateDTO coordinate = new CoordinateDTO();TextPosition tp = textPositions.get(i);// X坐标 直接获取的字体位置 ,也可以加上了字体的长度 tp.getX()+ + tp.getFontSize()Float x = tp.getX();// Y坐标 减去的字体的长度 tp.getPageHeight() - tp.getY() - 4 * tp.getFontSize()Float y = tp.getPageHeight() - tp.getY();coordinate.setX(x);coordinate.setY(y);coordinate.setLength(tp.getFontSize());pageList.add(coordinate);}}}}
}
ReportUtils.java
/*** @FileName: ReportUtils.java* @creator yongzhizean* @date 2023年2月17日 下午5:16:52* @editor* @Description:* @version V1.0*/
package ...包位置;import ...CoordinateDTO位置;
import ...PdfBoxKeyWordPosition位置;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdfparser.PDFStreamParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.springframework.stereotype.Service;import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;/*** * @ClassName: ReportUtils * @Description: pdf电子签章* @author yongzhizean* @date 2023年2月17日 下午5:16:52* @version V2.0*/
@Service
@Slf4j
public class ReportUtils {/*** * 生成新的报表* * @date 2023年2月17日 下午4:59:15* @author yongzhizean* @param url* 报表、pdf文档的地址* @param imageUrl* 签章图片地址* @param key* 需要签章的文字* @return* @throws Exception* @return byte[]*/public byte[] getNewReport(String url, String imageUrl, String key) throws Exception {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();try {log.info("访问报表Url:" + url);// 根据url获取文件流InputStream is = getFile(url);PDDocument doc = PDDocument.load(is);// 获取需要签章的文字坐标PdfBoxKeyWordPosition pdf = new PdfBoxKeyWordPosition(key, doc, false);List<CoordinateDTO> wordsPcoordinates = pdf.getCoordinate();log.info("获取新的textLocalDTO 带坐标:" + wordsPcoordinates.toString());// 替换坐标中的文字为空,并且赋值图片try {// 防止替换的文字盖住章或签字,先进行所有的替换,再进行所有的赋值for (CoordinateDTO coordinate : wordsPcoordinates) {// 获取需要替换的页面PDPage page = doc.getPage(coordinate.getPageNum() - 1);// 原本想根据key删除页面文本,但是deleteKey(page, textLocalDTO.getKey())未生效// 生成一个白色的矩形盖住需要替换的文本,实现替换功能PDPageContentStream contentStream = new PDPageContentStream(doc, page,PDPageContentStream.AppendMode.APPEND, true, true);contentStream.setNonStrokingColor(new Color(255, 255, 255));contentStream.addRect(coordinate.getX() - 1, coordinate.getY() - 1,coordinate.getLength() * key.length() + 1, coordinate.getLength() + 1);contentStream.fill();contentStream.close();}// 文件地址为空,签章文字坐标未找到返回原文件if (wordsPcoordinates.size() == 0 || StringUtils.isBlank(imageUrl)) {return toByteArray(is);}// 获取图片流InputStream imageInputStream = getFile(imageUrl);byte[] imageBtye = toByteArray(imageInputStream);// 指定页面,指定位置插入图片for (CoordinateDTO coordinate : wordsPcoordinates) {// 获取需要替换的页面PDPage page = doc.getPage(coordinate.getPageNum() - 1);PDPageContentStream contentStream = new PDPageContentStream(doc, page,PDPageContentStream.AppendMode.APPEND, true, true);PDImageXObject pdImage = PDImageXObject.createFromByteArray(doc, imageBtye, null);// 图片大小为80,找到替换位置x\y轴减去一半,保证在需要签章位置在中间contentStream.drawImage(pdImage, coordinate.getX() - 40, coordinate.getY() - 40, 80, 80);contentStream.close();}doc.save(byteArrayOutputStream);byte[] pdfBytes = byteArrayOutputStream.toByteArray();return pdfBytes;} catch (Exception e) {throw e;} finally {if (doc != null) {doc.close();}}} catch (Exception e) {throw e;}}/*** * 获取url后 下载文件* @date 2023年2月17日 下午5:16:28* @author yongzhizean* @param url* @return* @throws Exception* @return InputStream*/private InputStream getFile(String url) throws Exception {// 创建不同的 文件夹 目录InputStream inputStream = null;String fileName = url.substring(url.lastIndexOf("/") + 1);String newUrl = url.substring(0, url.lastIndexOf("/") + 1) + URLEncoder.encode(fileName, "utf-8");try {// 建立链接URL httpUrl = new URL(newUrl);HttpURLConnection conn = null;conn = (HttpURLConnection) httpUrl.openConnection();log.info("文件获取完毕,文件大小为:" + conn.getContentLength());// 获取网络输入流inputStream = httpUrl.openStream();} catch (Exception e) {log.error("文件获取失败:" + e.getMessage(), e);throw e;}return inputStream;}/**** InputStream 转换成byte[]* @date 2023年2月17日 下午5:17:53* @author yongzhizean* @param input* @return* @throws IOException* @return byte[]*/private byte[] toByteArray(InputStream input) throws IOException {ByteArrayOutputStream output = new ByteArrayOutputStream();byte[] buffer = new byte[1024 * 4];int n = 0;while (-1 != (n = input.read(buffer))) {output.write(buffer, 0, n);}return output.toByteArray();}/*** * 删除标记,未成功,不了解啥原因* @date 2023年2月17日 下午5:18:14* @author hushizhao* @param page* @param key* @throws IOException* @return void*/@SuppressWarnings("unused")private void deleteKey(PDPage page, String key) throws IOException {try {// 流对象来接收当前page的内容Iterator<PDStream> contents = page.getContentStreams();// PDF流对象剖析器(这将解析一个PDF字节流并提取操作数,等等)while (contents.hasNext()) {PDStream content = contents.next();// PDF流对象剖析器(这将解析一个PDF字节流并提取操作数,等等)PDFStreamParser parser = new PDFStreamParser(content.toByteArray());parser.parse();// 用list存流中的所有标记List<Object> tokens = parser.getTokens();for (int j = 0; j < tokens.size(); j++) {// 创建一个object对象去接收标记Object next = tokens.get(j);if (next instanceof Operator) {Operator op = (Operator) next;if (op.getName().equals("Tj")) {// COSString对象>>创建java字符串的一个新的文本字符串。COSString previous = (COSString) tokens.get(j - 1);// 将此字符串的内容作为PDF文本字符串返回。String string = previous.getString();// replaceAll>>替换字符string = string.replaceAll(key, "");System.out.println(string.getBytes("UTF-8"));// 重置COSString对象,设置字符编码格式previous.setValue(string.getBytes("UTF-8"));} else if (op.getName().equals("TJ")) {// COSArray是pdfbase对象数组,作为PDF文档的一部分COSArray previous = (COSArray) tokens.get(j - 1);// 循环previousfor (int k = 0; k < previous.size(); k++) {// 这将从数组中获取一个对象,这将取消引用该对象// 如果对象为cosnull,则返回nullObject arrElement = previous.getObject(k);if (arrElement instanceof COSString) {// COSString对象>>创建java字符串的一个新的文本字符串。COSString cosString = (COSString) arrElement;// 将此字符串的内容作为PDF文本字符串返回。String string = cosString.getString();// 替换string = string.replaceAll(key, "");log.info("替换字符1" + string);// 重置COSString对象cosString.setValue(string.getBytes("UTF-8"));}}}}}}} catch (Exception e) {log.error("pdf文本替换成空失败:" + e.getMessage(), e);throw e;}}
}
有大神解决了deleteKey方法不能用的话,欢迎评论指点,谢谢!
相关文章:
PDF文件替换内容(电子签章),依赖免费pdfbox
首先提前准备,压入如下依赖 <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId>…...
nvm 控制 node版本
nvm 官网 https://nvm.uihtm.com/ 1、卸掉nodejs,根据官网操作 2、如果之前安装过的nodejs,且安装的目录改变了,需重新配置系统环境 第一步:打开此电脑 > 右键属性 > 高级系统设置 > 环境变量 第二步: 在系统变量中选中…...
javaEE 初阶 — 传输层 TCP 协议中的异常情况与面向字节流的粘包问题
文章目录1 粘包问题1.1 什么是粘包问题1.2 如何解决粘包问题2 异常情况TCP 的十个特性:确认应答机制 超时重传机制 连接管理机制 滑动窗口 流量控制与拥塞控制 延迟应答与捎带应答 1 粘包问题 1.1 什么是粘包问题 面向字节流引入了一个比较麻烦的粘包问题。 …...
IP路由基础
——IP路由基础(IA)—— HCIA全套笔记已经上线(arpAAAvlanTrunk链路聚合vlan间通信ACL广域网技术以太网交换...........)_孤城286的博客-CSDN博客 目录 ——IP路由基础(IA)—— (1&#…...
12.centos7部署sonarqube9.6
12.centos7部署sonarqube9.6环境:sonarqube9.6Postgresql13JDK11sonarqube9.6下载地址:Postgresql13 rpm下载地址:JDK11下载地址:准备工作:修改文件句柄数(最大文件数)和用户最大进程数限制修改…...
大学四年自学Java编程,现在拿到28万年薪的offer,还是觉得挺值的
最近刚拿到美团的Java后端工程师的offer,(底薪、奖金、补贴、年终奖、五险一金)总包加在大概有28万的年薪,实际到手不会有这么多,但是我对于这个待遇还是非常满意的。说来还是非常的感慨,我属于那种从大一到…...
MySQL的日志详解
目录 一.介绍 日志分类 二.错误日志 三.二进制日志—binlog 概述 日志格式 操作 四.查询日志 五.慢查询日志 一.介绍 在任何一种数据库中,都会有各种各样的日志,记录着数据库工作的方方面面,以帮助数据库管理员追踪数据库曾经发生过的…...
输出该股票所有收盘比开盘上涨3%以上的日期
1:输出该股票所有收盘比开盘上涨3%以上的日期 #codingutf-8 import tushare as ts import pandas as pd import numpy as np#获取某支股票的历史行情数据 dfts.get_hist_data(code600519,start2001-01-01) #将互联网上的数据获取并且存储到本地 df.to_csv(./maotai…...
数值卡,让数据可视化玩出新花样丨三叠云
数值卡 路径 仪表盘 >> 仪表盘设计 功能简介 1. 数值卡增加「数值标题」、「图标」、「进度条」功能,使得应用场景更为广泛,实现数据可视化,让用户能够轻松地获取、处理信息。 2.「数据模型」支持0个维度1个指标、1个维度1个指标。…...
有这几个表现可能是认知障碍前兆
我国目前对于认知障碍的认知率、就诊率、诊断率很低,然而认知障碍如果能在早期发现,并及时治疗,生活质量会有效提高,缓解家属的精神和经济负担。所以,认知障碍的前兆一定要了解。1.记忆力减退,一周内的重要…...
java面试题-阿里真题详解
前言 大家好,我是局外人一枚,最近有不少粉丝去阿里巴巴面试了,回来之后总结不少难题给我,以下是面试的真题,跟大家一起来讨论怎么回答。 阿里一面 1、说⼀下ArrayList和LinkedList区别 ⾸先,他们的底层数…...
JSON格式解析关键词搜索API
为了进行此平台API的调用,首先我们需要做下面几件事情。 1、 获取一个KEY。 2、 参考API文档里的接入方式和示例。 3、查看测试工具是否有需要的接口,响应实例的返回字段是否符合参数要求。 4、利用平台的文档中心和API测试工具,对接口进…...
【Java基础】泛型(二)-泛型的难点:通配符
本文将尝试将通配符和泛型中的继承,多态一并讲解 关于泛型中继承的注意事项 因为Integer、Double继承了Number,根据多态性,以下语句是合法的 Number n new Integer(10); // OK, 父类引用变量可以指向子类对象 n 2.9 // OK,n实…...
黑马】后台管理-两个括号的坑
记录一下这两天的坑没想到后台管理系统上线这两天都没有搞明白1.首先第一个坑是使用node.js的express中间件框架创建一个微型服务器,然后将vue脚手架生成的dist文件夹的文件放入里面了 ,把项目加载到web服务器之后运行node .\app.js,页面显示…...
05:进阶篇 - 使用 CTKWidgets
作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 CTKWidgets 包含了一组 Qt 部件,用于生物医学成像应用程序。当然,即使你的程序与医学无关,很多部件也是很有参考意义的。 在 CTK 源码中,有很多选项开关,可以控制你想要编译的内容(详见:04:进阶篇 …...
【YOLO V5】代码复现过程
接上篇,讲到如何从mask转成YOLOv5训练需要的txt数据集格式,这篇就在此基础上进行模型训练预测和部署转换吧! 目录 1.环境准备 2.YOLO训练 2.1 数据集准备 2.2 data.yaml准备 2.3 yolov5.yaml准备 2.4 训练命令 3.YOLO预测 3.1OLOv5 P…...
汽车如何实现制动
汽车如何实现制动 汽车如何实现制动 难点答疑:汽车刹车时,四个车轮是如何制动的?制动机理是什么? 第一步:驾驶员踩下制动踏板,推动制动主缸 第二步:制动主缸将制动液的压力通过制动管道传递到四…...
cmake 引入第三方库(头文件目录、库目录、库文件)
程序的编写需要用到头文件,程序的编译需要lib文件,程序的运行需要dll文件,因此cmake引入第三方库其实就是将include目录、lib目录、bin目录引入工程。 目录 1、find_package(批量引入库文件和头文件) 2、include_dir…...
插件开发版|Authing 结合 APISIX 实现统一可配置 API 权限网关
当开发者在构建网站、移动设备或物联网应用程序时,API 网关作为微服务架构中不可或缺的控制组件,是流量的核心进出口。通过有效的权限管控,可以实现认证授权、监控分析等功能,提高 API 的安全性、可用性、拓展性以及优化 API 性能…...
deepinlinux v20安装rust和tauri并配置vscode开发工具过程
rust 很快进入linux内核开发,作为高效后台语言值得学习 tauri是代替electron的跨平台框架,不打包浏览器内核,所以打包出来体积小 安装rust 命令 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh 安装后看版本 rustc -V 看构…...
通俗易懂的机器学习——sklearn鸢尾花分类(KNN)
前言 KNN算法是机器学习中较为简单的入门算法,其主要思想是选取k个与待预测点相近的数据,观察他们的类别,本着离谁近就更像谁的思路对于待预测点进行预测,本文将针对使用sklearn进行KNN算法的使用进行详解 数据预处理 在正式开…...
操作系统引论
操作系统是管理硬件和软件的一种应用程序。操作系统是运行在计算机上最重要的一种软件,它管理计算机的资源和进程以及所有的硬件和软件。它为计算机硬件和软件提供了一种中间层,使应用软件和硬件进行分离,让我们无需关注硬件的实现࿰…...
优质 CS 读博 (PhD) 经验贴汇总
前言 如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 Advice for early-stage Ph.D. students 读博的核心是在研究上取得进展,只有在研究上取得一些进展ÿ…...
SpringCloud学习笔记 - @SentinelResource的fallbackblockHandler配置详解 - sentinel
1. sentinel服务负载均衡测试 sentinel默认开启了负载均衡的轮询模式,为了测试sentinel服务负载均衡的效果,需要先创建两个服务提供者和一个服务消费者。 1.1. 分别创建两个服务提供者-支付服务9003、9004 1. 添加pom依赖: 提供者只需要将…...
华为OD机试题 - 静态扫描最优成本(JavaScript)
最近更新的博客 2023新华为OD机试题 - 斗地主(JavaScript)2023新华为OD机试题 - 箱子之形摆放(JavaScript)2023新华为OD机试题 - 考古学家(JavaScript)2023新华为OD机试题 - 相同数字的积木游戏 1(JavaScript)2023新华为OD机试题 - 最多等和不相交连续子序列(JavaScri…...
mysql大数据量批量提交
DROP PROCEDURE IF EXISTS test.insert_bacth_commit_test1;CREATE PROCEDURE test.insert_bacth_commit_test1()begindeclare start_num int default 0; -- 初始设置起始行数declare end_num int default 5;-- 初始设施结束行数declare cnt_srouce int default 0; -- 定义源表…...
IP SAN组网配置
目录一、确认网络连接畅通二、服务器端ISCSI启动器配置1.以root身份登录2.验证是否已安装iSCSI启动器3.安装iSCSI启动器4.启动iSCSI服务5.给iSCSI启动器命名6.扫描目标器7.登录目标器8.将登录目标器行为设置为自启动三、主机多路径配置四、存储配置五、主机挂载背景:…...
面试7分看能力,3分靠嘴皮,剩下90分就靠这份Java面试八股文
有句话说的好,面试中7分靠能力,3分靠嘴皮刚开始面试的时候,介绍项目一般都是凸显我们技能的重中之重,它对一次面试的成败可以说具有决定性作用,这就涉及到我们的表达能力了,有人说我其实水平都在线…...
api接口如何对接?
对于很多产品小白或求职者而言,API接口是一个产品和研发领域的专业术语,大家可能在文章或者PRD中都已经有接触过API接口的概念。 实际上,接口的应用已经非常广泛和成熟,这个概念主要活跃在公司内部的各系统之间的衔接和对接以及公…...
毕业2年不到选择跳槽,居然拿到25K的薪资,简直了···
本人本科就读于某普通院校,毕业后通过同学的原因加入软件测试这个行业,角色也从测试小白到了目前的资深工程师,从功能测试转变为测试开发,并顺利拿下了某二线城市互联网企业的Offer,年薪 30W 。 选择和努力哪个重要&am…...
受欢迎的大连网站建设/实时军事热点
我们辛辛苦苦做一个网站不容易,一不留神还会被搜索引擎清0给k了,难道搜索引擎给清0了,我们就放弃吗,那样的话也太伤心了。下面我就来谈谈被搜索引擎k的几种类型及处理方式。一\ 大量的网站同一时间被k如果你的网站被k了࿰…...
武汉平价网站建设/网络seo是什么工作
链接:https://ac.nowcoder.com/acm/contest/5646/J来源:牛客网题目描述对输入的字符串进行排序后输出输入描述:多个测试用例,每个测试用例一行。每行通过,隔开,有n个字符,n<100输出描述:对于每组用例输出一…...
大学网站建设目标/百度联盟推广
ffmpeg.exe -i F:\闪客之家\闪客之歌.mp3 -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\11.flv ffmpeg -i F:\01.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\test.flv 使用-ss参数 作用(time_off set the start time offset),可以从指…...
电子商务网站有哪些内容/关键词完整版
密集而有序的弹道攻击 以及有序的动态群体角色冲锋 带来的视觉冲击力极强 哪怕是像素级的单位 所造成的画面感也可以是宏伟的 转载于:https://www.cnblogs.com/dandansang/p/7133610.html...
wordpress h1标签/免费平台
文章目录散列查找1. 基本思想2. 基本工作3. 散列函数的构造1. 考虑因素2. 数字关键词1. 直接定址法2. 除留余数法3. 数字分析法4. 折叠法5. 平方取中法3. 字符串关键字1. ASCII码加和法2. 前3个字符移位法3. 移位法4. 冲突处理方法1. 常用策略2. 开放定址法1. 线性探测2. 平方探…...
个人网站有商业内容备案/微博推广有用吗
整编:Snow、UNA如今,在市场经济高度发达的当下,趋势与环境也更迭得越来越快,整个社会的消费观念、品味、需求也都处在不断变迁当中。而在新消费时代下,年轻消费群体重新定义市场,不管是传统消费人群心态与品…...