java查找PDF关键字坐标 并且标记出来

  • 导入POM依赖
  • 代码
  • 关键点说明

导入POM依赖

<!--使用itextpdf,比pdfbox简单些-->
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.2</version>
</dependency>
<!--必须加入这个,否则中文会乱码或为空-->
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version>
</dependency>

代码

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import com.itextpdf.text.pdf.parser.Vector;import lombok.Data;public class PdfMatchKeyword {/*** 用于供外部类调用获取关键字所在PDF文件坐标* @param filepath* @param keyWords* @return*/public static List<KeyWordPosition> getKeyWordsByPath(String filepath, String keyWords) {List<KeyWordPosition> matchItems = null;try{PdfReader pdfReader = new PdfReader(filepath);matchItems = getKeyWords(pdfReader, keyWords);} catch (IOException e) {e.printStackTrace();}return matchItems;}/*** 获取关键字所在PDF坐标* @param pdfReader* @param keyWords* @return*/private static List<KeyWordPosition> getKeyWords(PdfReader pdfReader, String keyWords) {int page = 0;List<KeyWordPosition> matchItems = new ArrayList<>();try{int pageNum = pdfReader.getNumberOfPages();StringBuilder allText = null;//遍历页for (page = 1; page <= pageNum; page++) {//只记录当页的所有内容,需要记录全部页放在循环外面List<ItemPosition> allItems = new ArrayList<>();//扫描内容MyTextExtractionStrategy myTextExtractionStrategy = new MyTextExtractionStrategy(allItems, page);PdfTextExtractor.getTextFromPage(pdfReader, page, myTextExtractionStrategy);//当页的文字内容,用于关键词匹配allText = new StringBuilder();//一个字一个字的遍历for (int i=0; i<allItems.size(); i++) {ItemPosition item = allItems.get(i);allText.append(item.getText());//关键字存在连续多个块中if(allText.indexOf(keyWords) != -1) {KeyWordPosition keyWordPosition = new KeyWordPosition();//记录关键词每个字的位置,只记录开始结束标记时会有问题List<ItemPosition> listItem = new ArrayList<>();for(int j=i-keyWords.length()+1; j<=i; j++) {listItem.add(allItems.get(j));}keyWordPosition.setListItem(listItem);keyWordPosition.setText(keyWords);matchItems.add(keyWordPosition);allText.setLength(0);}}}} catch (Exception e) {e.printStackTrace();}return matchItems;}/*** 添加矩形标记* @param oldPath* @param newPath* @param matchItems 关键词* @param color 标记颜色* @param lineWidth 线条粗细* @param padding 边框内边距* @throws DocumentException* @throws IOException*/public static void andRectangleMark(String oldPath, String newPath, List<KeyWordPosition> matchItems, BaseColor color, int lineWidth, int padding) throws DocumentException, IOException{// 待加水印的文件PdfReader reader = new PdfReader(oldPath);// 加完水印的文件PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(newPath));PdfContentByte content;// 设置字体// 循环对每页插入水印for (KeyWordPosition keyWordPosition:matchItems){//一个关键词的所有字坐标List<ItemPosition> oneKeywordItems = keyWordPosition.getListItem();for(int i=0; i<oneKeywordItems.size(); i++) {ItemPosition item = oneKeywordItems.get(i);ItemPosition preItem = i==0?null:oneKeywordItems.get(i-1);// 水印的起始content = stamper.getOverContent(item.getPage());// 开始写入水印content.setLineWidth(lineWidth);content.setColorStroke(color);//底线content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getBottom()-padding);if(i!=0 && preItem!=null && (preItem.getRectangle().getBottom()-padding)==(item.getRectangle().getBottom()-padding) && (preItem.getRectangle().getRight()+padding)!=(item.getRectangle().getLeft()-padding)) {content.moveTo(preItem.getRectangle().getRight()+padding, preItem.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);}//上线content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getTop()+padding);if(i!=0 && preItem!=null && (preItem.getRectangle().getTop()+padding)==(item.getRectangle().getTop()+padding) && (preItem.getRectangle().getRight()+padding)!=(item.getRectangle().getLeft()-padding)) {content.moveTo(preItem.getRectangle().getRight()+padding, preItem.getRectangle().getTop()+padding);content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);}//左线if(i==0) {content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);}//右线if(i==(oneKeywordItems.size()-1)) {content.moveTo(item.getRectangle().getRight()+padding, item.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getTop()+padding);}content.stroke();}}stamper.close();}public static void main(String[] args) throws Exception {String keyword = "移动机器人";String sourcePdf = "C:\\Users\\chenyang-054\\Desktop\\3388.pdf";String watermarkPdf = "C:\\Users\\chenyang-054\\Desktop\\3388-mark.pdf";Long start = System.currentTimeMillis();System.out.println("开始扫描....");List<KeyWordPosition> matchItems = getKeyWordsByPath(sourcePdf, keyword);System.out.println("扫描结束["+(System.currentTimeMillis()-start)+"ms],共找到关键字["+keyword+"]出现["+matchItems.size()+"]次");start = System.currentTimeMillis();System.out.println("开始添加标记....");andRectangleMark(sourcePdf, watermarkPdf, matchItems, BaseColor.RED, 2, 2);System.out.println("标记添加完成["+(System.currentTimeMillis()-start)+"ms]");}
}/*** @ClassName: ItemPosition* @Description: 字体的位置信息* @author chenyang-054* @date 2021-04-09 09:14:36*/
@Data
class ItemPosition{private Integer page;private String text;//这个字的矩形坐标private Rectangle rectangle;
}/*** @ClassName: KeyWordPosition* @Description: 需要高亮显示的关键字坐标信息* @author chenyang-054* @date 2021-04-09 11:28:56*/
@Data
class KeyWordPosition{private String text;private List<ItemPosition> listItem;
}/*** @ClassName: MyTextExtractionStrategy* @Description: 记录所有位置+字体信息,这种方式获取坐标信息和字体信息方便一点* @author chenyang-054* @date 2021-04-09 11:00:31*/
class MyTextExtractionStrategy implements TextExtractionStrategy{private List<ItemPosition> positions;private Integer page;public MyTextExtractionStrategy() {}public MyTextExtractionStrategy(List<ItemPosition> positions, Integer page) {this.positions = positions;this.page = page;}@Overridepublic void beginTextBlock() {// TODO Auto-generated method stub}@Overridepublic void renderText(TextRenderInfo renderInfo) {ItemPosition ItemPosition = new ItemPosition();Vector bottomLeftPoint = renderInfo.getDescentLine().getStartPoint();Vector topRightPoint = renderInfo.getAscentLine().getEndPoint();//记录矩形坐标Rectangle rectangle = new Rectangle(bottomLeftPoint.get(Vector.I1), bottomLeftPoint.get(Vector.I2),topRightPoint.get(Vector.I1), topRightPoint.get(Vector.I2));ItemPosition.setPage(page);ItemPosition.setRectangle(rectangle);ItemPosition.setText(renderInfo.getText());positions.add(ItemPosition);}@Overridepublic void endTextBlock() {// TODO Auto-generated method stub}@Overridepublic void renderImage(ImageRenderInfo renderInfo) {// TODO Auto-generated method stub}@Overridepublic String getResultantText() {// TODO Auto-generated method stubreturn null;}
}

关键点说明

  1. itextpdf中坐标系为第一象限,原点在每页的左下角

  2. TextExtractionStrategy ,自定义MyTextExtractionStrategy,通过renderText方法可以获取位置和字体信息;

  3. 每页分开判断,此代码例子中,关键词判断通过每页内容字符串.indexOf来判断的,如果关键词正好在上下页就判断不了了,可以继续改进,把allText和allItems放到页循环外就可以了;

  4. 关键词检索,通过indexOf来判断很简单,如需多个关键词或敏感词库之类的,需要自己拓展算法和词库或其他规则;

  5. 标记功能,不论是后台画还是前端画矩形圈,不能只通过关键词的开始位置结束位置来画,因为会碰到换行/换页/有空格的情况,最好通过关键词的每个字的坐标去画矩形。否则会变成这样(图中关键词是:斯坦福研究院)

  6. 其他都写在注释里了,直接运行就可以了。

java查找PDF关键字坐标 并且标记出来相关推荐

  1. java提取PDF文字坐标

    常用java操作PDF的库有PDFbox和itext,下面我会介绍如何使用PDFbox和itext来提取PDF的文字坐标. 一.itext提取文字坐标 itext版本:5.5.6,低版本的可能没有提供 ...

  2. 使用itext查找PDF关键字具体坐标-亲测有效

    项目里需要引入的pom <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all&l ...

  3. php对pdf关键字定位,如何在PDF文件中快速查找关键字

    有时候我们在阅读和编辑PDF文章时需要对PDF文件里的重要关键词进行查找,但如果PDF文章内容过长,怎么才能快速查找出想要查找的关键字? 想要在PDF文件中快速查找出关键字,那么利用迅捷PDF编辑器进 ...

  4. java 查找关键字_java实现简单的关键字查找

    需求:从一个指定的字符串中,查找是否存在指定的关键字,有则将其按顺序找出.例如:从"我在开会,一会打电话,然后去吃饭" 查找是否含有 "教研"."上课 ...

  5. JAVA替换PDF文字

    前言: 以下是通过网上查阅资料,东拼西凑实现的一个使用java替换pdf文字的功能.使用的是itextpdf.jar 参考: https://blog.csdn.net/sdizoea/article ...

  6. JAVA 替换pdf中文字

    java 读取PDF文件内容进行替换 需要使用到的包 监听类(对需要替换的内容关键词进行匹配) 实体类(保存关键字字体格式信息以及其位置) 工具类(对关键字进行替换) 测试类 需要使用到的包      ...

  7. 使用java创建pdf 并返回流给前端

    使用java创建pdf 并返回流给前端 业务需求,页面点击打印预览文件,然后点击打印调用系统(浏览器)打印,经网上查阅资料,自己整理后记录下来 首先是自己整理的帮助类 import cn.bt.com ...

  8. Java生成PDF文件,java面试题,java初级笔试题

    写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. 一. ...

  9. Java生成PDF文件_自用

    Java生成PDF文件 一.前言 前几天,做ASN条码收货模块,需要实现打印下载收货报表,经一番查找,选定iText--用于生成PDF文档的一个Java类库.废话不多说,进入正题. 二.iText简介 ...

  10. java基础:关键字

    关键字: 1.被Java语言赋予特定含义的单词 2.特点: 全部小写 3.注意事项: A:goto和const作为保留字存在. B:类似于Notepad++这样的高级记事本会对关键字有特殊颜色标记 在 ...

最新文章

  1. 阻止应用继承的NTFS权限
  2. Android面试题目之(9) 幽灵引用
  3. pythonATM自动存取款机7天密码保护
  4. [Redis6]配置文件详解
  5. 四年从P7到P9,这个阿里小二的秘诀是给自己挖坑
  6. MySQL 基础———— UNION 联合查询
  7. qt程序中使用 环境变量_目的:使用CUDA环境变量CUDA_VISIBLE_DEVICES来限定CUDA程序所能使用的GPU...
  8. 滚动图片广告_女排赢球可喜看台马桶广告扎眼 网友:去男足赛场!别在这儿蹭热点...
  9. Axure 点图片外区域即隐藏_澳网红分享麦当劳隐藏饮料:咖啡混可乐再加点这个,神仙级好喝...
  10. 从零开始——基于角色的权限管理01(补充)
  11. Windows平台上实现P2P服务(一)
  12. tl-wn821n无线网卡驱动 linux,tl-wn821n无线网卡驱动下载
  13. linux 时间戳几字节,字节转换跟时间戳转换
  14. 新员工来到项目组的愿景_为您的项目设定愿景
  15. python爬虫爬取网页图片存储本地_Python爬虫抓取糗百的图片,并存储在本地文件夹...
  16. 吾爱破解python百度文库下载源码_python版百度音乐下载软件和源码
  17. docker启动elasticsearch容器put数据时: SERVICE_UNAVAILABLE/1/state not recovered /initialized
  18. PS中的LAB颜色模式有什么作用?给人像磨皮就很实用!
  19. Vector-常用CAN工具(软件篇)-CANoe Trace
  20. centos7下安装pg数据库

热门文章

  1. 服务器server.c、搜索serach.c
  2. GoLang之iface 和 eface 的区别是什么(3)
  3. c语言输出菱形for循环_c语言输出菱形(c语言for循环打印菱形)
  4. 计算机cpu的字母,笔记本电脑CPU型号后缀字母HQ、U、Y含义详解
  5. CPU的后缀到底是什么意思?
  6. xp无法访问win7计算机,xp系统访问win7共享文件夹提示无权限如何解决
  7. 以下不是dns服务器的作用,以下不是DNS服务的作用的是( )。
  8. 计算机无法进行磁盘,电脑硬盘无法分区怎么办
  9. matlab 判断 正态分布,用MATLAB判断一组数据是否符合正态分布
  10. css背景随机,CSS如何随机定义网页中的背景颜色