栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

PDF识别文字、关键字,获取对应坐标,用于插入电子签名

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

PDF识别文字、关键字,获取对应坐标,用于插入电子签名

*java识别pdf中的关键字,获取关键字坐标 *

今天遇到个需求,需要在pdf中识别关键字的坐标位置并插入电子签名(png,jpg),在网上找了很多的案例,发现不同的pdf识别出来效果不一样,有的pdf识别是一个文字一个文字,有的是一段文字一段文字。最终发现,由于pdf来源不同(word转换、excel转换、图片转换)导致识别的效果有所差异。

于是自己整理了一份案例,效果还算完美

效果展示

废话不多说
使用依赖:itextpdf-5.5.13.jar
常见itextpdf各个版本【0积分免费下载】 下载地址

  1. 新建DTO实体,用于接收返回的坐标信息
public class MatchItem {
    
    private Integer pageNum;

    
    private Float x;

    
    private Float y;

    
    private Float pageWidth;

    
    private Float pageHeight;

    
    private String content;

    public Integer getPageNum() {
        return pageNum;
    }

    public void setPageNum(Integer pageNum) {
        this.pageNum = pageNum;
    }

    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 getPageWidth() {
        return pageWidth;
    }

    public void setPageWidth(Float pageWidth) {
        this.pageWidth = pageWidth;
    }

    public Float getPageHeight() {
        return pageHeight;
    }

    public void setPageHeight(Float pageHeight) {
        this.pageHeight = pageHeight;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "MatchItem [pageNum=" + pageNum + ", x=" + x + ", y=" + y
                + ", pageWidth=" + pageWidth + ", pageHeight=" + pageHeight
                + ", content=" + content + "]";
    }

}

2.新建工具类,用处识别文字坐标

public class AutoMatch {

    public static List matchPage(String fileName, String keyword) throws Exception {
        List items = new ArrayList();
        PdfReader reader = new PdfReader(fileName);
        int pageSize = reader.getNumberOfPages();
        for (int page = 1; page <= pageSize; page++) {
            items.addAll(matchPage(reader, page, keyword));
        }
        return items;
    }

    public static List matchPage(PdfReader reader, Integer pageNumber, String keyword) throws Exception {
        KeyWordPositionListener renderListener = new KeyWordPositionListener();
        renderListener.setKeyword(keyword);
        PdfReaderContentParser parse = new PdfReaderContentParser(reader);
        Rectangle rectangle = reader.getPageSize(pageNumber);
        renderListener.setPageNumber(pageNumber);
        renderListener.setCurPageSize(rectangle);
        parse.processContent(pageNumber, renderListener);
        return findKeywordItems(renderListener, keyword);
    }

    public static List findKeywordItems(KeyWordPositionListener renderListener, String keyword) {
        //先判断本页中是否存在关键词
        //所有块LIST
        List allItems = renderListener.getAllItems();
        StringBuffer sbtemp = new StringBuffer("");
        //将一页中所有的块内容连接起来组成一个字符串。
        for (MatchItem item : allItems) {
            sbtemp.append(item.getContent());
        }
        //一页组成的字符串没有关键词,直接return
        if (sbtemp.toString().indexOf(keyword) == -1) {
            return renderListener.getMatches();
        }
        //第一种情况:关键词与块内容完全匹配的项
        List matches = renderListener.getMatches();

        //第二种情况:多个块内容拼成一个关键词,则一个一个来匹配,组装成一个关键词
        sbtemp = new StringBuffer("");
        List tempItems = new ArrayList();
        for (MatchItem item : allItems) {
            //1,关键词中存在某块 2,拼装的连续的块=关键词 3,避开某个块完全匹配关键词
            //关键词 中国移动 而块为 中 ,国,移动
            //关键词 中华人民 而块为中,华人民共和国 这种情况解决不了,也不允许存在

            if (keyword.indexOf(item.getContent()) != -1 && !keyword.equals(item.getContent())) {
                System.out.println(item.getContent());
                tempItems.add(item);
                sbtemp.append(item.getContent());
                //如果暂存的字符串和关键词 不再匹配时
                if (keyword.indexOf(sbtemp.toString()) == -1) {
                    sbtemp = new StringBuffer(item.getContent());
                    tempItems.clear();
                    tempItems.add(item);
                }
                //暂存的字符串正好匹配到关键词时
                if (sbtemp.toString().equalsIgnoreCase(keyword)) {
                    MatchItem tmpitem = getRightItem(tempItems, keyword);
                    if (tmpitem != null) {
                        //得到匹配的项
                        matches.add(tmpitem);
                    }
                    //清空暂存的字符串
                    sbtemp = new StringBuffer("");
                    //清空暂存的LIST
                    tempItems.clear();
                    //继续查找
                    continue;
                }
            } else {
                //如果找不到则清空
                sbtemp = new StringBuffer("");
                tempItems.clear();
            }
        }
        //第三种情况:关键词存在块中
        for (MatchItem item : allItems) {
            if (item.getContent().indexOf(keyword) != -1 && !keyword.equals(item.getContent())) {
                matches.add(item);
            }
        }
        return matches;
    }

    public static MatchItem getRightItem(List tempItems, String keyword) {
        for (MatchItem item : tempItems) {
            if (keyword.indexOf(item.getContent()) != -1 && !keyword.equals(item.getContent())) {
                return item;
            }
        }
        return null;
    }

3.新建pdf监听类,重写源码方法

public class KeyWordPositionListener implements RenderListener {
    private List matches = new ArrayList<>();
    private List allItems = new ArrayList<>();
    private Rectangle curPageSize;

    
    private String keyword;
    
    private Integer pageNumber;

    public void beginTextBlock() {
        //do nothing
    }

    public void renderText(TextRenderInfo renderInfo) {
        String content = renderInfo.getText();
        content = content.replace("<", "").replace("《", "").replace("(", "").replace("(", "").replace(""", "").replace("'", "")
                .replace(">", "").replace("》", "").replace(")", "").replace(")", "").replace("、", "").replace(".", "")
                .replace(":", "").replace(":", "").replace(" ", "");
        Rectangle2D.Float textRectangle = renderInfo.getDescentLine().getBoundingRectange();
        MatchItem item = new MatchItem();
        item.setContent(content);
        item.setPageNum(pageNumber);
        item.setPageWidth(curPageSize.getWidth());
        item.setPageHeight(curPageSize.getHeight());
        item.setX((float)textRectangle.getX());
        item.setY((float)textRectangle.getY());
        if(!StringUtils.isEmpty(content)){
            if(content.equalsIgnoreCase(keyword)) {
                matches.add(item);
            }
        }else{
            item.setContent("空字符串");
        }
        allItems.add(item);//先保存所有的项
    }

    public void endTextBlock() {
        //do nothing
    }

    public void renderImage(ImageRenderInfo renderInfo) {
        //do nothing
    }

    
    public void setPageNumber(Integer pageNumber) {
        this.pageNumber = pageNumber;
    }

    
    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    
    public List getMatches() {
        return matches;
    }

    void setCurPageSize(Rectangle rect) {
        this.curPageSize = rect;
    }

    public List getAllItems() {
        return allItems;
    }

    public void setAllItems(List allItems) {
        this.allItems = allItems;
    }


}

4.编写测试案例

   public static void main(String[] args) throws Exception {
        List matchItemList = matchPage("pdf路径", "需要匹配的文案");
    }

返回坐标后,就可通过文字对应的坐标信息插入电子签名了。

提示:插入签名的话一般需要向不同方向设置偏移量,调整到自己理想位置,直接对X坐标或Y坐标进行加减即可。

pdf插入图片可见另一个帖子
点击跳转

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1010629.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号