亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java高效提取PDF文件指定坐標的文本內(nèi)容實戰(zhàn)代碼

 更新時間:2024年01月18日 15:22:31   作者:沛沛老爹  
在日常工作中,有時可能會需要從龐大的PDF文檔中提取其中所包含的文本內(nèi)容,下面這篇文章主要給大家介紹了關于如何利用Java高效提取PDF文件指定坐標的文本內(nèi)容,需要的朋友可以參考下

前言

臨時接到一個緊急需要處理的事項。業(yè)務側(cè)一個同事有幾千個PDF文件需要整理:需要從文件中的指定位置獲取對應的編號和地址。
要的急,工作量大。所以就問到技術部有沒有好的解決方案。

問技術的話就只能寫個demo跑下了。

解決辦法

1. 研究下PDF文檔,找出解決方案

PDF的文檔看起來比較簡單,因為只是需要讀取兩個坐標位置的文本內(nèi)容,而且位置相對固定。所以就直接用java的第三方庫pdfbox來操作PDF文檔。

2. 找個能操作PDF的第三方庫pdfbox。

  • 先下載pdfbox的jar包。
    官網(wǎng)介紹
  • pdfbox能干啥:
    • pdfbox是Apache軟件基金會的一個開源項目,它提供API和工具來處理PDF文檔。

    • pdfbox是Apache PDFBox的Java版本,它提供了一個類庫,用于讀取,寫入,轉(zhuǎn)換和創(chuàng)建PDF文檔。

    • pdfbox支持處理各種PDF特性,如文本,字體,圖像,表單字段,注釋,書簽,頁面布局等。

    • pdfbox還提供了對加密和數(shù)字簽名PDF文檔的支持,以及對PDF文檔的提取和合并。

    • pdfbox還提供了對PDF文檔的驗證,簽名驗證,加密驗證和數(shù)字簽名的支持。

    • PDFBox是一個用于處理PDF文檔的Java庫。它提供了一組功能強大的API,可以用于創(chuàng)建、修改和提取PDF文檔的內(nèi)容。PDFBox可以用于各種用途,包括生成PDF文檔、提取文本和圖像、合并和拆分PDF文件、添加水印和書簽等。

    • PDFBox支持處理各種PDF特性,如文本、字體、圖像、表單字段、注釋、書簽、頁面布局等。它還提供了對加密和數(shù)字簽名PDF文檔的支持,以及對PDF文檔的高級操作,如提取文本位置信息、提取圖像和字體等。

3. maven加載包

pdfbox有三個大的版本,每個版本差異較大,這個時候如果要引入的時候,要注意對應的版本了,否則demo就有可能跑不起來。

pdfbox最新的大版本是3.0。作為新時代的青年,肯定要與時俱進。3.0肯定是要用上的。

4. 先驗證下第三方庫是否可行

下載jar包后,直接用java代碼跑下demo。 demo讀取pdf文檔內(nèi)容并輸出文本數(shù)據(jù)到控制臺

    import org.apache.pdfbox.pdmodel.PDDocument;
    import org.apache.pdfbox.text.PDFTextStripper;

    import java.io.File;
    import java.io.IOException;
    public class PDFBoxDemo {
        public static void main(String[] args) throws IOException {
            PDDocument document = PDDocument.load(new File("D:\\pdf\\test.pdf"));
            PDFTextStripper stripper = new PDFTextStripper();
            String text = stripper.getText(document);
            System.out.println(text);
            document.close();
        }
    }

發(fā)現(xiàn)demo跑起來后,報錯。
原因是因為demo是2.0的版本,而當前的jar包是3.0的版本。PDDocument.load這個修改為Loader.load就OK了。

接下來,就是如何獲取到指定坐標位置的文本內(nèi)容。

5. 確認文本在PDF文檔中的坐標位置。

確認PDF文本坐標一般有兩種方案。

1. 代碼校驗(最精準)

先用demo跑下,看下是否可以讀取到指定坐標位置的文本內(nèi)容。

 /**
    * 獲取文檔坐標
    * @param  file PDF文件對象
    * @param sourceTex 匹配的字符
    * @return 坐標
    */
   public static Point getPoint(File file,String sourceTex) {
       Point point = new Point();
       //獲取文檔坐標
      try {
        PDDocument document =  Loader.loadPDF(file);
        PDFTextStripper textStripper = new PDFTextStripper() {
            @Override
            protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
                if (text.contains(targetText)) {
                    TextPosition textPositionStart = textPositions.get(0);
                    TextPosition textPositionEnd = textPositions.get(textPositions.size()-1);
                    point.setX(textPositionStart.getX());
                    point.setY(textPositionStart.getY()); 
                }
            }
        };

        textStripper.setSortByPosition(true);
        textStripper.setStartPage(1);
        textStripper.setEndPage(document.getNumberOfPages());

        textStripper.getText(document);

        document.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return point;
    }

跑完demo后,發(fā)現(xiàn)可以讀取到指定坐標位置的文本內(nèi)容。
這里會有個小問題,就是返回的坐標點有的會有小數(shù)。因為當前返回類型float,所以需要轉(zhuǎn)換成int。

2. 最直接粗暴的方法。

  1. 福昕PDF文檔工具。
  2. 直接用福昕PDF文檔定位工具定位坐標。
  說實話,開發(fā)比較少用這種方式,因為感覺有點lower(其實是自己不太會用)

6. 整個demo先驗證第三方庫是否可行。

拿1個文件試試水

 public static void main(String[] args) {
        String filePath = "D:\\test\\test.pdf";
         try {
            PDDocument document = Loader.loadPDF(file);
            PDFTextStripperByArea  textStripper = new PDFTextStripperByArea ();
            Rectangle rectangle = new Rectangle(80,120, 250,10);
            String regionName = "regionName";
            textStripper.addRegion(regionName, rectangle);
            PDPage page = document.getPage(0);
            textStripper.extractRegions(page);
            String text = textStripper.getTextForRegion(regionName);
  
            System.out.println(text);
          
            textStripper.setSortByPosition(true);
            textStripper.setStartPage(1);
            textStripper.setEndPage(document.getNumberOfPages());
            textStripper.getText(document);
            document.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
      
    }

結果能夠正常輸出對應的文本內(nèi)容。

7. 整活上代碼。

奉上全部demo代碼

package com.example.demo;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson2.JSON;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import org.apache.pdfbox.text.TextPosition;
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;


import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Desc: 驗證pdfbox的可行性
 *
 * @author admin
 * @date since 2023/8/8 18:44
 */

public class PdfDemo {
	//要匹配的位置內(nèi)容點
    private  static final String[] target= {"name", "address"};
    public static void main(String[] args) {
       ExcelWriter excelWriter= ExcelUtil.getWriter("D:\\test\\pdf\\test.xls");
       String folderPath = "D:\\test\\pdf";
       File folder = new File(folderPath);
       if (folder.exists() && folder.isDirectory()) {
           List<Map<String,Object>>  mps =  listPdfFiles(folder);
           excelWriter.write(mps, true);
       } else {
           System.out.println("Invalid folder path.");
       }
       excelWriter.close();
    }
	/**
     * 獲取pdf文件列表
     *
     * @param folder 文件夾
     * @return {@code List<Map<String,Object>>}
     */
    private static  List<Map<String,Object>>  listPdfFiles(File folder) {
        List<Map<String,Object>> mps = new ArrayList<>();
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    listPdfFiles(file); // 遞歸調(diào)用,處理子文件夾
                } else {
                    String fileName = file.getName();
                    if (fileName.toLowerCase().endsWith(".pdf")) {
                        mps.add(getLineData(file));
                    }
                }
            }
        }
        return mps;
    }
    /**
     * 行數(shù)據(jù)
     *
     * @param file 文件
     * @return {@code Map<String,Object>}
     */
    public static Map<String,Object> getLineData(File file){
        Map<String,Object> lineData = new HashMap<>(target.length+2);
        List<Point> pointList =  getPoint(file);
        String[]  arr=  getPointValue(file, pointList.stream().map(s -> new Rectangle(s.getX(), s.getY(), 260, 10)).toArray(Rectangle[]::new));
        if(arr.length>=target.length) {
        for(int i=0;i<target.length;i++)
        {
            lineData.put(target[i], arr[i]);
        }
            lineData.put("fileName", file.getName().toLowerCase().replace(".pdf", ""));
        }
      return lineData;
    }
 	/**
     * 獲得PDF指定坐標點文本值
     *
     * @param file       文件
     * @param rectangles 矩形坐標
     * @return {@code String[]}
     */
    public  static String[] getPointValue( File file,Rectangle... rectangles){
        String[] textArr = new String[rectangles.length];
       // String text="";
        try {
            PDDocument document = Loader.loadPDF(file);
            PDFTextStripperByArea  textStripper = new PDFTextStripperByArea ();

            for(int i = 0; i < rectangles.length;i++   ) {
                Rectangle rectangle =rectangles[i];
                String regionName = "regionName"+rectangle.getX()+rectangle.getY();
                textStripper.addRegion(regionName, rectangle);
                PDPage page = document.getPage(0);
                textStripper.extractRegions(page);
                // 獲取區(qū)域的text
                String text = textStripper.getTextForRegion(regionName);
                text = text.replace("\u0000","-").replace(" ","");
                System.out.println(">>text"+text);
                textArr[i]=text;
            }

            textStripper.setSortByPosition(true);
            textStripper.setStartPage(1);
            textStripper.setEndPage(document.getNumberOfPages());

            textStripper.getText(document);

            document.close();
        }catch (IOException e) {
            e.printStackTrace();
        }

        return  textArr;
    }

    public  static List<Point> getPoint( File file){
        List<Point> pointList=new ArrayList<>();
        try {
        PDDocument document =  Loader.loadPDF(file);
        PDFTextStripper textStripper = new PDFTextStripper() {
            @Override
            protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
                for(String target:target){
                    if (text.contains(target)) {
                        Point point = new Point();
                        TextPosition textPositionEnd = textPositions.get(textPositions.size() - 1);
                        point.setX((int) textPositionEnd.getEndX());
                        point.setY((int) textPositionEnd.getY());
                        pointList.add(point);
                    }
                }
            }
        };

        textStripper.setSortByPosition(true);
        textStripper.setStartPage(1);
        textStripper.setEndPage(document.getNumberOfPages());
        textStripper.getText(document);
        document.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(">>>>>pointList" + JSON.toJSONString(pointList));
        return pointList;
    }
} 

8. 驗證代碼可行性

整理出來的excel,檢查里面有些空格沒有處理,就讓業(yè)務自己批量替換一下。

因為代碼只是一次性用的,就沒有怎么進行封裝了??傮w來講業(yè)務同事比較滿意。

結論

  • 第三方庫pdfbox可以操作PDF文檔。3.0版本之后和歷史版本相差比較大,最好先閱讀下源碼。
  • 坐標定位的話,可以用第三方也可以代碼定位
  • 如果代碼后續(xù)想復用的話,最好抽離出公共方法
  • 文件比較多的情況下,建議增加多線程處理。

總結 

到此這篇關于Java高效提取PDF文件指定坐標的文本內(nèi)容的文章就介紹到這了,更多相關Java提取PDF文件指定坐標文本內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java中l(wèi)ogback?自動刷新不生效的問題解決

    Java中l(wèi)ogback?自動刷新不生效的問題解決

    本文主要介紹了Java中l(wèi)ogback?自動刷新不生效的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • Jmeter邏輯控制器事務控制器使用方法解析

    Jmeter邏輯控制器事務控制器使用方法解析

    這篇文章主要介紹了Jmeter邏輯控制器事務控制器使用方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • 一文了解SpringBoot是如何連接數(shù)據(jù)庫的

    一文了解SpringBoot是如何連接數(shù)據(jù)庫的

    Spring Boot提供了一系列的開箱即用的功能和特性,使得開發(fā)人員可以快速構建和部署應用程序,下面這篇文章主要給大家介紹了關于SpringBoot是如何連接數(shù)據(jù)庫的相關資料,需要的朋友可以參考下
    2023-06-06
  • spring cloud zuul修改請求url的方法

    spring cloud zuul修改請求url的方法

    這篇文章主要給大家介紹了關于spring cloud zuul修改請求url的方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用spring cloud具有一定的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-09-09
  • spring boot整合jsp及設置啟動頁面的方法

    spring boot整合jsp及設置啟動頁面的方法

    這篇文章主要給大家介紹了關于spring boot整合jsp及設置啟動頁面的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用spring boot具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-09-09
  • Java異常java.lang.UnsatisfiedLinkError: no opencv_java320 in java.library.path的解決

    Java異常java.lang.UnsatisfiedLinkError: no opencv_ja

    這篇文章主要介紹了Java異常java.lang.UnsatisfiedLinkError: no opencv_java320 in java.library.path的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • jstack報錯Unable to open socket file解決

    jstack報錯Unable to open socket file解決

    這篇文章主要為大家介紹了jstack報錯Unable to open socket file的解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-02-02
  • Java重點之基于比較的七大排序

    Java重點之基于比較的七大排序

    最近幾天在研究排序算法,看了很多博客,發(fā)現(xiàn)網(wǎng)上有的文章中對排序算法解釋的并不是很透徹,而且有很多代碼都是錯誤的,所以我根據(jù)這幾天看的文章,整理了一個較為完整的排序算法總結,本文中的所有算法均有JAVA實現(xiàn),經(jīng)本人調(diào)試無誤后才發(fā)出,如有錯誤,請各位前輩指出
    2021-10-10
  • 詳解Spring Security 中的四種權限控制方式

    詳解Spring Security 中的四種權限控制方式

    這篇文章主要介紹了詳解Spring Security 中的四種權限控制方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • Mybatis超級強大的動態(tài)SQL語句大全

    Mybatis超級強大的動態(tài)SQL語句大全

    MyBatis的動態(tài)SQL是基于OGNL表達式的,它可以幫助我們方便的在SQL語句中實現(xiàn)某些邏輯,下面這篇文章主要給大家介紹了關于Mybatis超級強大的動態(tài)SQL語句的相關資料,需要的朋友可以參考下
    2022-05-05

最新評論