PDF模板查找关键字坐标

开发过程中会遇到很多给一个模板上赋值的任务,一般都是使用占位符等操作,对需要赋值的位置进行文本赋值,还有一种是找到关键字,然后获取其在文档中的位置,然后进行坐标偏移赋值。今天就来介绍第二种方式。

开始始终是我们的接口

    /*** PDF模板查找关键字坐标* @return 返回值*/@GetMapping(value = "/testNewPdf")@ResponseBodyvoid testNewPdf();

千变万变,接口不变

 @Overridepublic void testNewPdf() {testCreatePDF();}

还是接口 继续

    /*** .** @Description: 作用:  测试pdf相关* @Author: LXT* @Date: 2022/1/7 14:11*/public void testCreatePDF() {testQueryKeywordLastAddText();}

这里就要开始正常的代码逻辑了 , 先附上代码

 /*** .** @Description: 作用:  pdf查找关键字后,加文字* @Author: LXT* @Date: 2022/1/7 14:12*/private void testQueryKeywordLastAddText() {//初始化文件地址,或者其他位置的文件模板位置String initPdf = "D:\\Users\\User\\Desktop\\XXXX.pdf";logger.info("初始化之后的pdf地址" + initPdf);//关键字String keyword = "日期:";//调用工具类,查找关键字的位置信息float[] floats = QueryKeywordPositionUtil.queryKeywordPosition(initPdf, keyword);logger.info("关键字位置--" + JSON.toJSONString(floats));//要新加的文本String text = "2021 年 01 月 07 日";//调用工具类,进行文本赋值String endPath = KeywordLastAddTextUtil.keywordLastAddText(initPdf, floats, text);logger.info("pdf关键字后增加文字后地址--" + endPath);logger.info("pdf关键字后增加文字完成");}

代码简单明了 还是比较容易看懂的,
重点 来了 看下第一个工具类 查找关键字的

/*** .** @ClassName: QueryKeywordPositionUtil* @Description: 查找关键字位置坐标工具类* @Author: LXT* @Date: 2022/1/6 16:11*/
public class QueryKeywordPositionUtil {private static final Logger logger = LoggerFactory.getLogger(QueryKeywordPositionUtil.class);/*** .* @Description: 作用:  查找关键字位置坐标* @Author: LXT* @Date: 2022/1/7 14:40* @param pdfPath 入参 pdf地址* @param keyword 入参  关键字* @return float[] 分别为 float[0]所在页码  float[1]所在x轴 float[2]所在y轴*/public static float[] queryKeywordPosition(String pdfPath, String keyword) {try {//1.给定文件File pdfFile = new File(pdfPath);//2.定义一个byte数组,长度为文件的长度byte[] pdfData = new byte[(int) pdfFile.length()];//3.IO流读取文件内容到byte数组FileInputStream inputStream = null;try {inputStream = new FileInputStream(pdfFile);inputStream.read(pdfData);} catch (IOException e) {throw e;} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {}}}logger.info("读取pdf完成---" + pdfPath);//4.指定关键字// String keyword = "日期:";//5.调用方法,给定关键字和文件List<float[]> positions = findKeywordPostions(pdfData, keyword);logger.info("关键字" + keyword + "位置---" + JSON.toJSONString(positions));float page = 0;
//            float xxxx = 0;
//            float yyyy = 0;//6.返回值类型是  List<float[]> 每个list元素代表一个匹配的位置,分别为 float[0]所在页码  float[1]所在x轴 float[2]所在y轴System.out.println("total:" + positions.size());if (positions != null && positions.size() > 0) {for (float[] position : positions) {page = position[0];
//                    xxxx = position[1];
//                    yyyy = position[2];System.out.print("pageNum: " + (int) position[0]);System.out.print("\tx: " + position[1]);System.out.println("\ty: " + position[2]);if (page == 1) {logger.info("关键字" + keyword + "位置在第一页" + JSON.toJSONString(positions));return position;}}}} catch (Exception e) {logger.error("查找关键字位置坐标异常", e);}return null;}/*** findKeywordPostions 查找关键字位置** @param pdfData 通过IO流 PDF文件转化的byte数组* @param keyword 关键字* @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y* @throws IOException*/private static List<float[]> findKeywordPostions(byte[] pdfData, String keyword) throws IOException {List<float[]> result = new ArrayList<>();List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);if (charPositions == null || charPositions.size() < 1) {continue;}result.addAll(charPositions);}return result;}/*** .** @param pdfData 入参* @return java.util.List<com.utils.QueryKeywordPositionUtil.PdfPageContentPositions>* @Description: 作用:   查找关键字位置合集* @Author: LXT* @Date: 2022/1/7 10:37*/private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {PdfReader reader = new PdfReader(pdfData);List<PdfPageContentPositions> result = new ArrayList<>();int pages = reader.getNumberOfPages();for (int pageNum = 1; pageNum <= pages; pageNum++) {float width = reader.getPageSize(pageNum).getWidth();float height = reader.getPageSize(pageNum).getHeight();PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);//解析pdf,定位位置PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);PdfDictionary pageDic = reader.getPageN(pageNum);PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);try {processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);} catch (IOException e) {reader.close();throw e;}String content = pdfRenderListener.getContent();List<CharPosition> charPositions = pdfRenderListener.getcharPositions();List<float[]> positionsList = new ArrayList<>();for (CharPosition charPosition : charPositions) {float[] positions = new float[]{charPosition.getPageNum(), charPosition.getX(), charPosition.getY()};positionsList.add(positions);}PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();pdfPageContentPositions.setContent(content);pdfPageContentPositions.setPostions(positionsList);result.add(pdfPageContentPositions);}reader.close();return result;}private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {List<float[]> result = new ArrayList<>();String content = pdfPageContentPositions.getContent();List<float[]> charPositions = pdfPageContentPositions.getPositions();for (int pos = 0; pos < content.length(); ) {int positionIndex = content.indexOf(keyword, pos);if (positionIndex == -1) {break;}float[] postions = charPositions.get(positionIndex);result.add(postions);pos = positionIndex + 1;}return result;}private static class PdfPageContentPositions {private String content;private List<float[]> positions;public String getContent() {return content;}public void setContent(String content) {this.content = content;}public List<float[]> getPositions() {return positions;}public void setPostions(List<float[]> positions) {this.positions = positions;}}private static class PdfRenderListener implements RenderListener {private int pageNum;private float pageWidth;private float pageHeight;private StringBuilder contentBuilder = new StringBuilder();private List<CharPosition> charPositions = new ArrayList<>();public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {this.pageNum = pageNum;this.pageWidth = pageWidth;this.pageHeight = pageHeight;}public void beginTextBlock() {}public void renderText(TextRenderInfo renderInfo) {List<TextRenderInfo> characterRenderInfos = renderInfo.getCharacterRenderInfos();for (TextRenderInfo textRenderInfo : characterRenderInfos) {String word = textRenderInfo.getText();if (word.length() > 1) {word = word.substring(word.length() - 1, word.length());}Rectangle2D.Float rectangle = textRenderInfo.getAscentLine().getBoundingRectange();float x = (float) rectangle.getX();float y = (float) rectangle.getY();//这两个是关键字在所在页面的XY轴的百分比float xPercent = Math.round(x / pageWidth * 10000) / 10000f;float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;CharPosition charPosition = new CharPosition(pageNum, (float) x, (float) y);charPositions.add(charPosition);contentBuilder.append(word);}}public void endTextBlock() {}public void renderImage(ImageRenderInfo renderInfo) {}public String getContent() {return contentBuilder.toString();}public List<CharPosition> getcharPositions() {return charPositions;}}private static class CharPosition {private int pageNum = 0;private float x = 0;private float y = 0;public CharPosition(int pageNum, float x, float y) {this.pageNum = pageNum;this.x = x;this.y = y;}public int getPageNum() {return pageNum;}public float getX() {return x;}public float getY() {return y;}@Overridepublic String toString() {return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";}}}

主要是 queryKeywordPosition 这个 需要的参数就是pdf 位置 以及关键字
然后 开始读取pdf 找到文档中所有的关键字位置集合 重复的会反多个哦

我这里只需要操作第一页 所有就判断第一页就可以了 ,
具体是怎么查的关键字,还请高手一一解读,

然后回到 testQueryKeywordLastAddText 将唯一的位置信息返回,
然后进行关键字后增加文本操作
首先工具类 必不可少

/*** .** @ClassName: KeywordLastAddTextUtil* @Description: 关键字后增加文本工具类* @Author: LXT* @Date: 2022/1/7 14:23*/
public class KeywordLastAddTextUtil {private static final Logger logger = LoggerFactory.getLogger(KeywordLastAddTextUtil.class);/*** .** @param templatePath 入参 pdf文件* @param floatNum     入参 关键字位置* @param text     入参 新增文本* @return String 新的pdf地址* @Description: 作用: 关键字后增加文本* @Author: LXT* @Date: 2022/1/7 14:47*/public static String keywordLastAddText(String templatePath, float[] floatNum, String text) {logger.info("pdf--" + templatePath + "--增加文本---" + text);try {// 模板文件路径String newFileName = templatePath.replace(".pdf","addText.pdf");byte[] pdfBty = ClientUtil.readFileToByteArray(new File(templatePath));//pdf字节数组ClientUtil.writeByteArrayToFile(new File(newFileName), pdfBty);logger.info("输出pdf地址--" + newFileName);fileChannelCopy(new File(newFileName), new File(templatePath));PdfReader reader = new PdfReader(templatePath);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(newFileName));PdfContentByte overContent = stamper.getOverContent(1);//添加文字BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);overContent.beginText();overContent.setFontAndSize(font, 10);overContent.setTextMatrix(200, 200);// 位置x 左到右 越来越大// 位置y 下到上 越来越大// x: 80.04    y: 614.26263//字体大小为10  x 向右边偏移三个字 x+30//字体大小为10  y 向下边偏移一个字 y-10// float[1]所在x轴 float[2]所在y轴float xx = floatNum[1] + 30f;float yy = floatNum[2] - 10f;overContent.showTextAligned(Element.ALIGN_LEFT, text, xx, yy, 0);overContent.endText();stamper.close();return newFileName;} catch (Exception e) {System.out.println(e.getMessage());return null;}}/*** .** @param sources 入参 源文件* @param dest    入参 目标文件* @return void* @Description: 作用:  文件的输入输出流* @Author: LXT* @Date: 2022/1/7 14:41*/private static void fileChannelCopy(File sources, File dest) {try {FileInputStream inputStream = new FileInputStream(sources);FileOutputStream outputStream = new FileOutputStream(dest);FileChannel fileChannelin = inputStream.getChannel();//得到对应的文件通道FileChannel fileChannelout = outputStream.getChannel();//得到对应的文件通道fileChannelin.transferTo(0, fileChannelin.size(), fileChannelout);//连接两个通道,并且从in通道读取,然后写入out通道inputStream.close();fileChannelin.close();outputStream.close();fileChannelout.close();} catch (Exception e) {e.printStackTrace();}}}

这个其实也好理解

入参就是 pdf 位置 关键字坐标 以及要添加的文本
首先是将这个pdf 复制一份以免对源文件造成损坏
然后就是设置字体的一些信息 当然了 可以在里边放置像文件了 或者图片了 等等其他 就不一一介绍了

PdfContentByte overContent = stamper.getOverContent(1);
这个是设置我文本要在第几页

然后文本的xy轴说明 一看就明白了 应该不用介绍 看不明白的私信

rotation 是旋转量 也就是旋转多少度

将文本输出的新的pdf中 整个过程就完成了 随后返回新的pdf地址

好了 ,给定一个pdf 然后查找关键字坐标 并在后面添加文本数据 整个流程就算完成了 需要增加的其他的还请自行研究。

对了 附上 pdf模板的截图


这是第一页 需要在日期后增加文本 由于不确定因素 只能去查找关键字
下边是最终效果

本文完,码值不易,记得点赞。

PDF模板查找关键字坐标相关推荐

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

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

  2. java itextpdf签章 根据关键字定位在pdf文件中的坐标

    最近接到个需求,根据所传关键字,定位关键字所在pdf文件中的坐标,然后盖章,其中所传参数还有关键字所在页数,和获取第几次出现的关键字,会传多个印章和关键字,每个印章对应一个关键字.自己先写了个简单de ...

  3. java 文字生成pdf,并创建自定义表单域pdf模板

    目录 本文总共知识点: pom 所有的import 生成带表格的pdf 另一种方式是指定坐标生成文本域 main方法: 创建表单域做为pdf模板: 创建签名域: 根据文字获取坐标位置 完整代码: 本文 ...

  4. PDF内根据关键字插入图片

    根据pdf内指定关键字的坐标插入图片,实现分为两个步骤. 1:查找出dpf内所有的关键字的坐标和关键字所在的页数. 2:根据查到的关键字位置出入图片: 引入 compile('com.itextpdf ...

  5. java pdf添加图片_java实现在pdf模板的指定位置插入图片

    本文实例为大家分享了java在pdf模板的指定位置插入图片的具体代码,供大家参考,具体内容如下 java操作pdf有个非常好用的库itextpdf,maven: com.itextpdf itextp ...

  6. java使用itext将图片放到pdf模板的指定位置

    java使用itext将图片放到pdf模板的指定位置 前面的准备步骤可以参考我的上一篇文章 这里直接上代码 这里用的图片是路径的形式,还有种情况是图片是base64的时候,这种情况就需要转一下图片格式 ...

  7. pdf模板工具JaspersoftStudio,JasperReport

    pdf模板工具JaspersoftStudio,JasperReport 概述 Jaspersoft    Studio是JasperReports库和JasperReports服务器的基于Eclip ...

  8. java pdf域插入img_java实现在pdf模板的指定位置插入图片

    本文实例为大家分享了java在pdf模板的指定位置插入图片的具体代码,供大家参考,具体内容如下 java操作pdf有个非常好用的库itextpdf,maven: com.itextpdf itextp ...

  9. java pdf工具类_Java PDF工具类(一)| 使用 itextpdf 根据PDF模板生成PDF(文字和图片)...

    Java PDF工具类(一)| 使用 itextpdf 根据设置好的PDF模板填充PDF(文字和图片) 相关文章: Java PDF工具类(二)| 使用 wkhtmltox 实现 HTML转PDF(文 ...

  10. Java生成PDF文档 iText使用PDF模板一

    最近在弄这个java生成pdf,哎,在网上查找了各种各样的学习资料,弄了几天,今天终于把这个效果简单的弄出来,所以,也把这个,我所走过的坑,作一个记录,提供接下来需要学习的人. 参考文献文档:http ...

最新文章

  1. 大道至简:软件工程实践者的思想——第七、八章感想
  2. Tensorboard安装和访问(pytorch+MobaXterm)
  3. 北京有个可以躺的酒吧——床吧(BED)
  4. 将VC++6.0的代码迁移到VS2005常见问题总结(Window核心编程第五版以前代码在VS2005无法编译的解决方案)...
  5. DevOps“兵器”60样,你都会使哪几样?
  6. [转]iOS开发使用半透明模糊效果方法整理
  7. java 包错_以下关于Java包的描述中,错误的是()
  8. Oracle查看用户、用户权限、用户表空间、用户默认表空间
  9. office选项-》高级-》显示 中, 显示此数目的“最近使用的文档” 为灰色,无法更改
  10. hadoop 依赖式job_每天一学:一个轻量级分布式任务调度框架 XXL-JOB
  11. 这才是设计 React 的万金油!
  12. 在虚拟DOM和Diff算法中为什么不建议使用index作为key值?
  13. linux定时备份文件到指定文件夹,Linux定时备份数据库到指定邮箱的方法
  14. CString转char*的两种方法讨论
  15. excel mysql仓库管理_怎样用excel数据库建立仓库管理系统?
  16. 唯一解的数独题目生成器——理解回溯法
  17. c语言程序设计教程答案王晓云,【单选题】华人图灵奖获得者是( ) A. 吴恩达 B. 王小云 C. 姚期智 D. 杨振宁...
  18. 2021年三亚旅游行业发展现状分析:旅游总收入达747.03亿元,占GDP的89.43%[图]
  19. 【尚医通】手机登录功能
  20. 什么证据可以证明婚内出轨?

热门文章

  1. 28部漫威电影按漫威时间全梳理
  2. 笔记本计算机在桌面显示,笔记本电脑开机后不显示桌面该怎么处理
  3. Android Studio安装(本人也是站在巨人肩膀上学习~)
  4. 十大排序算法(数据结构)
  5. “离职同事在工作群抢红包被踢”:学会退群,是职场人的基本修养
  6. 应用电子技术创新实验设计说明书
  7. Python爬虫生成二维码应用,突显个性味道
  8. DMA copy和CPU copy
  9. 计算机CPU风扇的功能及作用,CPU和风扇之间涂的是什么东西
  10. arp-scan使用