java获取pdf文字坐标_Java 获取PDF关键字坐标
一、使用 itextpdf 推荐使用
com.itextpdf
itextpdf
5.5.13.1
PdfKeyWordPosition.java
package com.util;
import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 获取pdf关键字坐标
*/
public class PdfKeyWordPosition {
private static final Logger log = LoggerFactory.getLogger(PdfKeyWordPosition.class);
/**
* 获取关键字坐标
* @param pdfData
* @param keyWord
* @return
*/
public static List> getWordsPcoordinate(byte[] pdfData, String keyWord){
List> result = new ArrayList<>();
PdfReader reader = null;
try {
// pdfData :可以是二进制,也可以是文件路径,两种方式选择一种
reader = new PdfReader(pdfData);
//获取pdf页数
int pages = reader.getNumberOfPages();
for (int pageNum = 1; pageNum <= pages; pageNum++) {
//每页的宽度
Float width = reader.getPageSize(pageNum).getWidth();
//每页的高度
Float height = reader.getPageSize(pageNum).getHeight();
RenderListenerHelper renderListenerHelper = new RenderListenerHelper(pageNum, width, height);
//解析pdf,定位位置
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(renderListenerHelper);
PdfDictionary pageDic = reader.getPageN(pageNum);
PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
//文本内容
String content = renderListenerHelper.getContent();
//文本每个字对应的坐标
List> charPositions = renderListenerHelper.getCharPositions();
for (int i = 0; i < content.length(); i++){
//获取关键字所在位置
int keyIndex = content.indexOf(keyWord, i);
if (keyIndex == -1){
break;
}
result.add(charPositions.get(keyIndex));
i = keyIndex + 1;
}
}
} catch (Exception e){
log.error("获取pdf关键字坐标失败:{}", e);
} finally {
reader.close();
}
return result;
}
/**
* 重写 itextpdf 的 RenderListener 类里的方法
*/
private static class RenderListenerHelper implements RenderListener {
private int pageNum;
private float pageWidth;
private float pageHeight;
private StringBuilder contentBuilder = new StringBuilder();
private List> charPositions = new ArrayList<>();
public RenderListenerHelper(int pageNum, float pageWidth, float pageHeight) {
this.pageNum = pageNum;
this.pageWidth = pageWidth;
this.pageHeight = pageHeight;
}
public String getContent() {
return contentBuilder.toString();
}
public List> getCharPositions() {
return charPositions;
}
//step 2 遇到"BT"执行
@Override
public void beginTextBlock() {
}
//step 3 文字主要处理方法
@Override
public void renderText(TextRenderInfo renderInfo) {
//获取文本内容每个字信息集合
List characterRenderInfos = renderInfo.getCharacterRenderInfos();
for (TextRenderInfo textRenderInfo : characterRenderInfos) {
String word = textRenderInfo.getText();
if (word.length() > 1) {
word = word.substring(word.length() - 1);
}
//关键字上边缘坐标
//Rectangle2D.Float boundingRectange = textRenderInfo.getAscentLine().getBoundingRectange();
//关键字标准坐标(中间)
Rectangle2D.Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();
//关键字下边缘坐标
//Rectangle2D.Float boundingRectange = textRenderInfo.getDescentLine().getBoundingRectange();
//正常坐标
Float x = boundingRectange.x;
Float y = boundingRectange.y;
/*
//中心坐标
float x = (float)boundingRectange.getCenterX();
float y = (float)boundingRectange.getCenterY();
//最大最小坐标
double x = boundingRectange.getMinX();
double y = boundingRectange.getMaxY();
//这两个是关键字在所在页面的XY轴的百分比
float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;
*/
Map coordinate = new HashMap<>();
coordinate.put("x", x);
coordinate.put("y", y);
coordinate.put("pageNum", pageNum); //页数
coordinate.put("fontWidth", boundingRectange.width); //字体长度
coordinate.put("fontHeight", boundingRectange.height); //字段高度
charPositions.add(coordinate);
contentBuilder.append(word);
}
}
//step 4(最后执行的,只执行一次),遇到“ET”执行
@Override
public void endTextBlock() {
}
//step 1(图片处理方法)
@Override
public void renderImage(ImageRenderInfo renderInfo) {
}
}
public static void main(String[] args) {
try {
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
is = new FileInputStream("D:\\test.pdf");
byte[] buffer = new byte[is.available()];
Integer n = 0;
while ((n = is.read(buffer)) != -1) {
bos.write(buffer, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] bytes = bos.toByteArray();
List> wordsPcoordinates = getWordsPcoordinate(bytes,"日期");
for (Map map : wordsPcoordinates){
System.out.println("x坐标 -> " + map.get("x"));
System.out.println("y坐标 -> " + map.get("y"));
System.out.println("页数 -> " + map.get("pageNum"));
System.out.println("字体长度 -> " + map.get("fontWidth"));
System.out.println("字段高度 -> " + map.get("fontHeight"));
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、使用 pdfbox
org.apache.pdfbox
pdfbox
2.0.20
PdfBoxKeyWordPosition.java
package com.util;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 继承 pdfbox 中 PDFTextStripper类,获取关键字坐标
*/
public class PdfBoxKeyWordPosition extends PDFTextStripper {
private static final Logger log = LoggerFactory.getLogger(PdfBoxKeyWordPosition.class);
//关键字字符数组
private char[] key;
//PDF文件路径
private String pdfPath;
//二进制文件
private byte[] bytes;
//坐标集合
private List> coordinates = new ArrayList<>();
// 当前页坐标集合
private List> pageList = new ArrayList<>();
/*//使用文件路径
public PdfBoxKeyWordPosition(String keyWords, String pdfPath) throws IOException {
super();
super.setSortByPosition(true);
this.pdfPath = pdfPath;
char[] key = new char[keyWords.length()];
for (int i = 0; i < keyWords.length(); i++) {
key[i] = keyWords.charAt(i);
}
this.key = key;
}*/
//使用二进制数据
public PdfBoxKeyWordPosition(String keyWords, byte[] bytes) throws IOException {
super();
super.setSortByPosition(true);
this.bytes = bytes;
char[] key = new char[keyWords.length()];
for (int i = 0; i < keyWords.length(); i++) {
key[i] = keyWords.charAt(i);
}
this.key = key;
}
// 获取坐标信息
public List> getCoordinate(){
try {
//document = PDDocument.load(new File(pdfPath)); 文件地址
document = PDDocument.load(bytes); //文件二进制数据
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 (Map li : pageList) {
li.put("pageNum", i);
}
coordinates.addAll(pageList);
pageList.clear();
}
} catch (Exception e) {
log.error("获取pdf关键字坐标失败:{}", e);
} finally {
pageList.clear();
try {
if (document != null) {
document.close();
}
} catch (IOException e) {
log.error("关闭文件失败:{}", e);
}
}
return coordinates;
}
// 获取坐标信息
@Override
protected void writeString(String string, List 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) {
Map coordinate = new HashMap<>();
TextPosition tp = textPositions.get(i);
// X坐标 在这里加上了字体的长度,也可以直接 tp.getX()
Float x = tp.getX() + tp.getFontSize();
// Y坐标 在这里减去的字体的长度,也可以直接 tp.getPageHeight() - tp.getY()
Float y = tp.getPageHeight() - tp.getY() - 4 * tp.getFontSize();
coordinate.put("x", x);
coordinate.put("y", y);
pageList.add(coordinate);
}
}
}
}
public static void main(String[] args) {
try {
InputStream is = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
is = new FileInputStream("D:\\test.pdf");
byte[] buffer = new byte[is.available()];
Integer n = 0;
while ((n = is.read(buffer)) != -1) {
bos.write(buffer, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] bytes = bos.toByteArray();
PdfBoxKeyWordPosition pdf = new PdfBoxKeyWordPosition("日期", bytes);
List> wordsPcoordinates = pdf.getCoordinate();
for (Map map : wordsPcoordinates){
System.out.println("x坐标 -> " + map.get("x"));
System.out.println("y坐标 -> " + map.get("y"));
System.out.println("页面 -> " + map.get("pageNum"));
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
java获取pdf文字坐标_Java 获取PDF关键字坐标相关推荐
- PDF文字怎么编辑,PDF文档编辑方法
有时候遇到PDF文件不是自己制作的或者是制作的有点匆忙,会有文字遗漏或者打错的时候,我们使用就会有点麻烦就需要把文件中的文字进行编辑修改,那么具体怎么做呢?小伙伴们都挺好奇吧,今天就来跟大家分享一下. ...
- java 读取pdf签名域_Java 获取PDF中的数字签名信息
本文以Java代码演示如何获取PDF文档中的数字签名信息,包括签名人.签名位置.日期.原因.联系方式.签名在文档中的坐标等等. 程序环境包括: Jdk 1.8.0(版本要求>=1.6.0版本即可 ...
- java代码条形码链接网址_Java在PDF中添加条形码
java开发从入门到精通第2版疯狂 80.8元 包邮 (需用券) 去购买 > 条形码,是由宽度不等的多个黑条和空白所组成,用以表达一组信息的图形标识符.通过给文档添加条形码,可以直观,快捷地访问 ...
- java 获取手机归属地_java 获取手机归属地
java 获取手机归属地 [2021-01-30 20:46:44] 简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace("/( ...
- java 读取pdf签名域_Java给PDF签名
1.引入依赖 com.e-iceblue e-iceblue http://repo.e-iceblue.cn/repository/maven-public/ e-iceblue spire.pdf ...
- java中volatile的含义_java中volatile关键字的含义
(支持原创)本篇文章非原创,原文章地址: http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 在java线程并发处理中,有一 ...
- java获取鼠标在窗口_Java获取窗口鼠标坐标以及键盘按键
Java中的鼠标和键盘事件 1.使用MouseListener借口处理鼠标事件 鼠标事件有5种:按下鼠标键,释放鼠标键,点击鼠标键,鼠标进入和鼠标退出 鼠标事件类型是MouseEvent,主要方法有: ...
- java写入pdf文件图片_Java编辑PDF写入文字 插入图片
package com.test; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Font; import com.itex ...
- java提取图像坐标_java获取图片的GPS信息
简介 EXIF(Exchangeable Image File format)是"可交换图像文件"的缩写,当中包含了专门为数码相机的照片而定制的元数据,可以记录数码照片的拍摄参数. ...
- java pdf 插入图片_java在pdf模板的指定位置插入图片
个人感觉pdf的操作比word舒心多了 java操作pdf有个非常好用的库itextpdf,maven: com.itextpdf itextpdf 5.5.6 com.itextpdf itext- ...
最新文章
- Linux追加文件内容并在内容前加上该文件名(awk, FILENAME功能妙用)
- Jquery对象的文档处理,CSS和事件
- 【控制】《自动控制原理》胡寿松老师-第7章-线性离散系统的分析与校正
- 差动机器人毕业设计_双轮差动机器人曲线算法设计与实现
- Linux下window转unix文件格式
- linux同步硬件和系统时钟,liunx系统下时钟不同步会出现问题 怎么同步Linux 的系统时钟和硬件时钟?...
- 立足优势,你的网站会更精彩
- 小米高管称redmi暂没有曲面屏 网友:Redmi K40 Pro曲面屏无望了
- DocumentHelper解析xml文件
- GPUImageMovie播放控制
- stm32获取绝对值编码器值(SSI,串行通讯)
- 【平头哥蓝牙Mesh网关开发套件试用体验】蓝牙mesh网关接入网络
- 专注世界排名的Alexa.com宣布关站
- C#Task执行线程及其相关问题
- L2-3 清点代码库【STL】
- 卧槽!GitHub标星7.9K star,抢茅台酒脚本竟然开源了!网友:已抢到,真香!
- [2023-01 持续更新] 谷歌学术google镜像/Sci-Hub可用网址/Github镜像可用网址总结
- 前端 - 博客系统(页面设计)
- web前端培训机构出来的能找到工作吗?30道Web前端面试题收藏版
- PMBOK指南第六版—项目成本管理总结
热门文章
- 步进电机控制器编程实例C语言,步进电机控制器原理_步进电机控制器编程实例...
- Transaction
- xp计算机设置密码6,如何设置开机密码_xp系统电脑设置开机密码的方法 - 驱动管家...
- python模拟支付宝扫码登录_Python爬虫模拟登录支付宝并获取订单信息
- 蒙特卡罗方法C语言求定积分,蒙特卡罗方法计算定积分
- 计算机管理有U盘 为啥不显示,U盘插入电脑后不显示怎么办?
- Word serach(Medium)
- SLAM学习 | 使用小觅相机MYNTEYE-S1030收集数据集
- 以生活中的例子快速理解十个设计模式
- excel打不开_mac版excel死机该如何恢复?