【PDFBox】PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档

这篇文章,主要介绍PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档。

目录

一、PDFBox操作文本

1.1、读取所有页面文本内容

1.2、读取指定页面文本内容

1.3、写入文本内容

1.4、替换文本内容

(1)自定义PDTextStripper类

(2)创建KeyWordEntity实体类

(3)下载字体文件

(4)创建PDFUtil工具类

(5)运行效果

(6)不足之处


一、PDFBox操作文本

PDFBox操作文本内容,需要使用文本提取器PDTextStripper对象实现,这个PDTextStripper类提供了对文本内容操作的方法,例如:getText()获取文本,writeString()写入字符串等等,下面介绍PDFBox操作文本的几种情况。

1.1、读取所有页面文本内容

一个PDF文档是由多个页面组成的,某一个页面中都可能会包含文本内容,PDTextStripper类提供的【getText()】方法,可以获取到整个PDF文档的文本内容,案例代码如下所示:

package pdfbox.demo.text;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;import java.io.File;
import java.io.IOException;/*** @version 1.0.0* @Date: 2023/7/18 9:03* @Author ZhuYouBin* @Description: 读取PDF文档中所有纯文本内容*/
public class ReadAllText {public static void main(String[] args) throws IOException {// 1、加载指定PDF文档PDDocument document = PDDocument.load(new File("D:\\demo.pdf"));// 2、创建文本提取对象PDFTextStripper stripper = new PDFTextStripper();// 3、获取指定页面的文本内容String text = stripper.getText(document);System.out.println("获取文本内容: " + text);// 4、关闭document.close();}
}

1.2、读取指定页面文本内容

有些情况下,我们可能是需要获取某一个页面中的文本内容,这个时候可以通过PDTextStripper类设置页面边界,也就是设置提取哪些页面中的文本内容,只需要调用【setStartPage()】和【setEndPage()】方法即可,案例代码如下所示:

package pdfbox.demo.text;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;import java.io.File;
import java.io.IOException;/*** @version 1.0.0* @Date: 2023/7/18 9:03* @Author ZhuYouBin* @Description: 读取PDF文档中所有纯文本内容*/
public class ReadPageText {public static void main(String[] args) throws IOException {// 1、加载指定PDF文档PDDocument document = PDDocument.load(new File("D:\\demo.pdf"));// 2、创建文本提取对象PDFTextStripper stripper = new PDFTextStripper();// 指定页面读取内容stripper.setStartPage(0); // 设置起始页面,这里设置成0,就表示读取第一个页面stripper.setEndPage(0); // 设置结束页面,这里设置成0,就表示读取第一个页面// 3、获取指定页面的文本内容String text = stripper.getText(document);System.out.println("获取文本内容: " + text);// 4、关闭document.close();}
}

1.3、写入文本内容

前几篇文章已经介绍过了如何使用PDFBox写入纯文本内容到PDF文档里面,写入内容可以写入单行内容,也可以写入多行文本内容,可以参考文章:

【【PDFBox】PDFBox操作PDF文档之创建PDF文档、加载PDF文档、添加空白页面、删除页面、获取总页数、添加文本内容、PDFBox坐标系】。

1.4、替换文本内容

替换文本内容,PDFBox并没有提供替换文本内容的方法,这里我是采用了某种方式来实现替换文本内容的功能,大致思路:

  • 首先读取文本内容,获取到替换的文本在PDF文档中的页面坐标位置。
  • 获取到替换文本的坐标之后,将这块区域内容写入一个矩形框,矩形背景颜色采用白色,也就是覆盖替换的文本。
  • 在白色矩形区域里面,重新写入替换之后的文本内容。
  • 采用这种思路,就可以大致实现替换指定文本的功能啦。

(1)自定义PDTextStripper类

要想获取到文本的坐标信息,必须自定义一个类,继承自PDTextStripper类,然后重写【writeString()】方法,这个方法有两个参数:

  • 第一个参数是text:表示当前读取到的文本内容。
  • 第二个参数是List<TextPosition>:表示当前文本内容中某一个字符的坐标信息。
package pdfbox.demo.text.keyword;import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
import org.apache.pdfbox.util.Matrix;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;/*** @version 1.0.0* @Date: 2023/7/18 10:18* @Author ZhuYouBin* @Description: 自定义文本提取器,获取查找文本的坐标位置*/
public class KeyWordPositionStripper extends PDFTextStripper {/*** 查找的关键字集合*/private final List<String> keyWordList;/*** 查找成功的关键字实体对象集合*/private final List<KeyWordEntity> keyWordEntityList = new ArrayList<>();public KeyWordPositionStripper(List<String> keyWordList) throws IOException {this.keyWordList = keyWordList;}@Overrideprotected void writeString(String text, List<TextPosition> positions) {int size = positions.size();for (String keyWord : keyWordList) {char[] chars = keyWord.toCharArray();for (int i = 0; i < size; i++) {// 获取当前读取的字符String currentChar = positions.get(i).getUnicode();// 当前字符 和 keyWord 关键字进行匹配if (!Objects.equals(currentChar, String.valueOf(chars[0]))) {continue;}int count = 1;int j;for (j = 1; j < chars.length && i + j < size; j++) {currentChar = positions.get(i + j).getUnicode();if (!Objects.equals(currentChar, String.valueOf(chars[j]))) {break;}count++;}// 匹配成功,记录文本的坐标位置if (count == chars.length) {TextPosition startPosition = positions.get(i);TextPosition endPosition = positions.get(i + j < size ? i + j : i + j - 1);// 创建实体对象KeyWordEntity entity = new KeyWordEntity();entity.setKeyWord(keyWord);// 获取起始字符坐标Matrix matrix = startPosition.getTextMatrix();float x = matrix.getTranslateX();float y = matrix.getTranslateY();// 获取结束字符坐标Matrix endMatrix = endPosition.getTextMatrix();float x2 = endMatrix.getTranslateX();// 获取字体大小float fontSizeInPt = startPosition.getFontSizeInPt();entity.setX(x);entity.setY(y - fontSizeInPt / 5);float width = i + j < size ? x2 - x : x2 - x + fontSizeInPt;entity.setWidth(width);entity.setHeight(fontSizeInPt);keyWordEntityList.add(entity);}}}}public List<KeyWordEntity> getKeyWordEntityList() {return keyWordEntityList;}
}

(2)创建KeyWordEntity实体类

创建一个KeyWordEntity实体类,用于表示需要查找的关键字文本,关键字也就是我们需要替换的文本内容,一般在实际开发中,就相当于是模板占位符内容。实体类需要设置关键字名称、文本的坐标信息。

package pdfbox.demo.text.keyword;import java.io.Serializable;/*** @version 1.0.0* @Date: 2023/7/18 11:22* @Author ZhuYouBin* @Description: 查找的关键字*/
public class KeyWordEntity implements Serializable {private String keyWord;private float x;private float y;private float width;private float height;public String getKeyWord() {return keyWord;}public void setKeyWord(String keyWord) {this.keyWord = keyWord;}public float getX() {return x;}public void setX(float x) {this.x = x;}public float getY() {return y;}public void setY(float y) {this.y = y;}public float getWidth() {return width;}public void setWidth(float width) {this.width = width;}public float getHeight() {return height;}public void setHeight(float height) {this.height = height;}
}

(3)下载字体文件

如果你不想使用PDFBox提供的字体,那么你可以使用外部字体文件,字体文件可以去【经典宋体简|经典|字体下载】网站下载。

(4)创建PDFUtil工具类

package pdfbox.demo.text.keyword;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.springframework.core.io.ClassPathResource;import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;/*** @version 1.0.0* @Date: 2023/7/18 16:01* @Author ZhuYouBin* @Description: 基于PDFBox的工具类*/
public class PDFUtil {/*** 读取PDF模板文件,替换指定关键字的数据* @param keyWordMap 需要替换的关键字数据,key表示占位符,value表示替换后的内容* @param pdfPath PDF模板文件的路径* @param destPdf 生成的目标PDF文件*/public static void replaceText(Map<String, String> keyWordMap, String pdfPath, String destPdf) throws IOException {if (keyWordMap == null || keyWordMap.keySet().size() <= 0) {return;}Set<String> keyWordSet = keyWordMap.keySet();// 1、读取PDF模板文件PDDocument document = PDDocument.load(new File(pdfPath));// 2、创建自定义文本提取器KeyWordPositionStripper stripper = new KeyWordPositionStripper(new ArrayList<>(keyWordSet));stripper.setSortByPosition(true);// 注意: writeString() 方法必须执行 getText() 方法之后才会执行stripper.getText(document);// 3、获取关键字实体对象List<KeyWordEntity> keyWordEntityList = stripper.getKeyWordEntityList();// 4、替换指定关键字文本内容PDPageContentStream stream = new PDPageContentStream(document, document.getPage(0), PDPageContentStream.AppendMode.APPEND, true);// 5、加载外部字体文件,这里是直接通过File加载,如果你是SpringBoot项目,则可以通过流加载PDType0Font font = PDType0Font.load(document, new File("D:\\simsun.ttf"));// 6、循环替换文本内容for (KeyWordEntity keyWord : keyWordEntityList) {stream.setNonStrokingColor(Color.WHITE);stream.addRect(keyWord.getX(), keyWord.getY(), keyWord.getWidth(), keyWord.getHeight());stream.fill();// 设置画笔颜色stream.setNonStrokingColor(Color.BLACK);// 替换关键字文本内容stream.beginText();stream.setFont(font, 14);stream.newLineAtOffset(keyWord.getX(), keyWord.getY());stream.showText(keyWordMap.get(keyWord.getKeyWord()));stream.endText();}// 关闭内容流stream.close();// 保存替换之后的文档document.save(destPdf);// 关闭文档document.close();}public static void main(String[] args) throws IOException {Map<String, String> keyWordMap = new HashMap<>();keyWordMap.put("{{name}}", "张三");keyWordMap.put("{{age}}", "25");keyWordMap.put("{{sex}}", "男");keyWordMap.put("{{address}}", "福建省厦门市");// 模拟测试PDFUtil.replaceText(keyWordMap, "D:\\pdfbox-template.pdf", "D:\\new-document.pdf");}
}

(5)运行效果

这里的PDF模板文件如下图所示:

使用PDFBox替换模板文件的内容之后,运行结果如下所示:

(6)不足之处

虽然这里可以实现替换文本内容,但是这个代码仍然存在一些不足之处,有以下几点:

  • 1、替换的文本位置无法保证和原文本内容对齐,需要自己根据实际模板,调整相应坐标位置。
  • 2、当替换的文本内容太多,会覆盖后面的文本内容。
  • 3、目前只能够替换指定页面的文本内容。
  • 4、其他不足。。。

到此,PDFBox操作文本就介绍完啦。

综上,这篇文章结束了,主要介绍PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/4867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Endless OS 上安装 ONLYOFFICE 桌面编辑器

ONLYOFFICE 桌面编辑器是一款基于依据 AGPL v.3 许可进行分发的开源办公套件。使用这款应用&#xff0c;您无需保持网络连接状态即可处理存储在计算机上的文档。本指南会向您介绍&#xff0c;如何在 Endless OS 上安装 ONLYOFFICE 桌面编辑器。 ONLYOFFICE 桌面版是什么 ONLYO…

Spring Boot进阶(55):SpringBoot之集成MongoDB及实战使用 | 超级详细,建议收藏

1. 前言&#x1f525; 前几期我们有介绍Mysql、Redis等数据库介绍及实战演示&#xff0c;对基本的数据存放有很好的共性&#xff0c;但是如果说遇到大面积的xml、Json、bson等格式文档数据存放&#xff0c;以上数据库并非是最优选择&#xff0c;最优选择是Mongodb数据库。 那么…

如何将jar 包下载到自定义maven仓库

下载命令 mvn install:install-file -Dfileartifactid-version.jar -DgroupIdgroupid -DartifactIdartifactid -Dversionversion -Dpackagingjar -DlocalRepositoryPath. -DcreateChecksumtrue参数解释 在上述命令中&#xff0c;需要替换以下参数&#xff1a; artifactid-vers…

HTTP原理解析-超详细

作者&#xff1a;20岁爱吃必胜客&#xff08;坤制作人&#xff09;&#xff0c;近十年开发经验, 跨域学习者&#xff0c;目前于海外某世界知名高校就读计算机相关专业。荣誉&#xff1a;阿里云博客专家认证、腾讯开发者社区优质创作者&#xff0c;在CTF省赛校赛多次取得好成绩。…

vue3+vue-router4:报错Uncaught (in promise) Error: Invalid navigation guard

报错图示&#xff1a; Error: Invalid navigation guard Uncaught (in promise) Error: Invalid navigation guard 错误影响描述&#xff1a; 配置开发、测试、生产时候&#xff0c;因为是公众号&#xff0c;所以想在开发环境下免鉴权&#xff0c;不走微信获取openid接口&a…

potplayer放大画面,画面拖拽。备份

放大画面&#xff1a; 按住alt和鼠标左键&#xff0c;就可以拖动放大后的画面了 窗口化示图

【DC-DC】APS54083 降压恒流驱动器大功率深度调光 舞台 RGB 汽车照明 台灯驱动芯片

产品描述 APS54083 是一款 PWM 工作模式,高效率、外围简单、外置功率 MOS 管&#xff0c;适用于 5-220V 输入高精度降压 LED 恒流驱动芯片。输出最大功率150W最大电流 6A。APS54083 可实现线性调光和 PWM 调光&#xff0c;线性调光脚有效电压范围 0.5-2.5V.PWM 调光频率范围 1…

学习babylon.js --- [3] 开启https

babylonjs提供WebVR功能&#xff0c;但是使用这个功能得用https&#xff0c;本文讲述如何使用自签名证书来开启https&#xff0c;基于第二篇文章中搭建的工程。 一 生成自签名证书 首先要安装openssl&#xff0c;这个去网上搜下就行了。安装完之后在终端下输入openssl回车可以…

MongoDB

MongoDB概述 MongoDB是一个基于分布式文件存储的数据库。由C语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 它支持的数据结构非…

状态模式:游戏、工作流引擎中常用的状态机是如何实现的?

从今天起&#xff0c;我们开始学习状态模式。在实际的软件开发中&#xff0c;状态模式并不是很常用&#xff0c;但是在能够用到的场景里&#xff0c;它可以发挥很大的作用。从这一点上来看&#xff0c;它有点像我们之前讲到的组合模式。 可以简短的回顾一下组合模式&#xff1a…

uniapp安卓签名证书生成,签名证书的SHA1,SHA256,MD5获取

uniapp安卓证书生成有两种方式&#xff0c;一种是去dcloud开发者中心生成证书&#xff0c;另一种是安装jre环境&#xff0c;自己生成证书 第一种 dcloud生成证书 去该项目对应的应用处&#xff0c;生成证书需要等几分钟&#xff0c;生成后可以查看证书信息 第二种 自己生成…

如何下载SRA存放在AWS的原始数据

通常&#xff0c;我们都是利用prefetch从NCBI上获取数据&#xff0c;然后用fasterp-dump/fastq-dump 转成fastq。但遗憾的SRA的数据是原数据的有损压缩&#xff0c;比如说我19年参与发表的文章里单细胞数据上传的是3个文件&#xff0c;但是当时的faster-dump/fastq-dump只能拆出…

【ArcGIS Pro二次开发】(46):要素类从上到下、从左到右排序

要素类经过编辑之后&#xff0c;【OBJECTID】字段会变得不规律。应部分网友要求&#xff0c;做了这个从上到下、从左到右排序的工具。 不过后来在ArcGIS Pro中发现了一个【排序】工具&#xff0c;已经可以完美实现这个功能需求&#xff0c;发现自己做了个白工。 不过做了不能白…

Ghost Buster Pro for mac(快速清理卸载的应用残存文件)

Ghost Buster Pro for mac可从您已卸载的应用程序中查找并删除文件。该应用程序速度快如闪电&#xff0c;可立即释放内存。 许多应用程序都安装在计算机上&#xff0c;但它们通常只会在您的计算机上停留很短的时间。每个应用程序都会创建文件&#xff0c;但删除应用程序不会删…

若依字典使用

若依字典使用 此文章使用的若依是大于3.7.0版本的 JS文件配置 main.js中引入全局变量和方法 import DictData from /components/DictData DictData.install()DictData.js配置 可以从DictData.js中看出在install方法中调用了字典查询接口&#xff0c;在install方法中可以做…

前端 | (五)CSS三大特性及常用属性 | 尚硅谷前端html+css零基础教程2023最新

学习来源&#xff1a;尚硅谷前端htmlcss零基础教程&#xff0c;2023最新前端开发html5css3视频 文章目录 &#x1f4da;CSS三大属性&#x1f407;层叠性&#x1f407;继承性&#x1f407;优先级 &#x1f4da;CSS常用属性&#x1f407;像素的概念&#x1f407;颜色的表示⭐️表…

火狐安卓版支持油猴了!后面将支持更多扩展插件

日前火狐浏览器每夜构建版的安卓版已经带来了更多扩展程序支持&#xff0c;这其中就包括大名鼎鼎的油猴扩展程序。本次火狐浏览器每夜构建版更新新增五款扩展程序支持&#xff0c;并且按照谋智基金会说法还会支持更多的扩展程序。 下载地址&#xff1a;https://ftp.mozilla.org…

WEB:FlatScience

背景知识 sql注入 SQLite数据库知识 SQLite3注入方法 题目 用dirsearch进行扫描&#xff0c;下面几个关键目录&#xff1a;robots.txt&#xff0c;login.php&#xff0c;admin.php&#xff0c;剩下的目录就是一些pdf格式的论文了 一个一个访问并查看源代码&#xff0c;在查看l…

windows下安装consul、springboot整合consul

Spring Cloud Consul通过自动配置和绑定到Spring Environment和其他Spring编程模型习语&#xff0c;为Spring Boot应用程序提供Consul集成。通过一些简单的注解&#xff0c;可以快速启用和配置应用程序内的常用模式&#xff0c;并使用Hashicorp的Consul构建大型分布式系统。提供…