java实现查找PDF关键字所在页码及其坐标

 更新时间:2019年09月05日 11:37:30   作者:消失的太阳  
这篇文章主要介绍了java实现查找PDF关键字所在页码及其坐标的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

1、因为最近有这方面的需求,用过之后记录一下。

2、此功能跟PDF中Ctrl+F性质一样,如果PDF中为图片形式的不支持定位到关键字。

import com.itextpdf.awt.geom.Rectangle2D.Float;
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 java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
 * 消失的太阳
 */
public class MyTest {
 public static void main(String[] args) throws IOException {
  //1.给定文件
  File pdfFile = new File("D://test.pdf");
  //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) {
    }
   }
  }
  //4.指定关键字
  String keyword = "消失的太阳:";
  //5.调用方法,给定关键字和文件
  List<float[]> positions = findKeywordPostions(pdfData, keyword);
  //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) {
    System.out.print("pageNum: " + (int) position[0]);
    System.out.print("\tx: " + position[1]);
    System.out.println("\ty: " + position[2]);
   }
  }
 }
 /**
  * findKeywordPostions
  * @param pdfData  通过IO流 PDF文件转化的byte数组
  * @param keyword  关键字
  * @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y
  * @throws IOException
  */
 public 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;
 }
 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());
    }
    Float rectangle = textRenderInfo.getAscentLine().getBoundingRectange();
    float x = (float)rectangle.getX();
    float y = (float)rectangle.getY();
//    float x = (float)rectangle.getCenterX();
//    float y = (float)rectangle.getCenterY();
//    double x = rectangle.getMinX();
//    double y = rectangle.getMaxY();
    //这两个是关键字在所在页面的XY轴的百分比
    float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
    float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;
//    CharPosition charPosition = new CharPosition(pageNum, xPercent, yPercent);
    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;
  }
  @Override
  public String toString() {
   return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
  }
 }
}

总结

以上所述是小编给大家介绍的java实现查找PDF关键字所在页码及其坐标,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

  • JAVA的Dubbo如何实现各种限流算法

    JAVA的Dubbo如何实现各种限流算法

    Dubbo是一种高性能的Java RPC框架,广泛应用于分布式服务架构中,在Dubbo中实现限流可以帮助服务在高并发场景下保持稳定性和可靠性,常见的限流算法包括固定窗口算法、滑动窗口算法、令牌桶算法和漏桶算法,在Dubbo中集成限流器可以通过实现自定义过滤器来实现
    2025-01-01
  • SpringBoot与SpringCache概念用法大全

    SpringBoot与SpringCache概念用法大全

    这篇文章主要介绍了SpringBoot与SpringCache的概念及基本用法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • SpringBoot入门教程详解

    SpringBoot入门教程详解

    SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化 Spring 应用的初始搭建以及开发过程。本文将详细为大家讲讲SpringBoot是使用,需要的可以参考一下
    2022-06-06
  • SpringCloud微服务熔断器Hystrix使用详解

    SpringCloud微服务熔断器Hystrix使用详解

    这篇文章主要介绍了Spring Cloud Hyxtrix的基本使用,它是Spring Cloud中集成的一个组件,在整个生态中主要为我们提供服务隔离,服务熔断,服务降级功能,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Spring Validator接口校验与全局异常处理器

    Spring Validator接口校验与全局异常处理器

    这篇文章主要介绍了Spring Validator接口校验与全局异常处理器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Java并发编程之Condition源码分析(推荐)

    Java并发编程之Condition源码分析(推荐)

    这篇文章主要介绍了Java并发编程之Condition源码分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Spring @Component自定义注解实现详解

    Spring @Component自定义注解实现详解

    @Component是一个元注解,意思是可以注解其他类注解,如@Controller @Service @Repository @Aspect。官方的原话是:带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化
    2022-09-09
  • SpringBoot集成Dubbo启用gRPC协议

    SpringBoot集成Dubbo启用gRPC协议

    这篇文章主要介绍了SpringBoot集成Dubbo启用gRPC协议,以及与原生 gRPC 在代码编写过程中的区别。感兴趣的同学可以参考阅读
    2023-04-04
  • MyBatis高级映射ResultMap解决属性问题

    MyBatis高级映射ResultMap解决属性问题

    对于数据库中对表的增删改查操作,我们知道增删改都涉及的是单表,而只有查询操作既可以设计到单表操作又可以涉及到多表操作,所以对于输入映射parameterType而言是没有所谓的高级映射的,也就是说高级映射只针对于输出映射
    2023-02-02
  • Java多线程并发编程和锁原理解析

    Java多线程并发编程和锁原理解析

    这篇文章主要介绍了Java多线程并发编程和锁原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论