如何查找网站根目录,室内装饰公司网站模板,中华建设网官网,做名宿比较好的网站前言
临时接到一个紧急需要处理的事项。业务侧一个同事有几千个PDF文件需要整理#xff1a;需要从文件中的指定位置获取对应的编号和地址。 要的急#xff0c;工作量大。所以就问到技术部有没有好的解决方案。 问技术的话就只能写个demo跑下了。
解决办法
1. 研究下PDF文档…
前言
临时接到一个紧急需要处理的事项。业务侧一个同事有几千个PDF文件需要整理需要从文件中的指定位置获取对应的编号和地址。 要的急工作量大。所以就问到技术部有没有好的解决方案。 问技术的话就只能写个demo跑下了。
解决办法
1. 研究下PDF文档找出解决方案
PDF的文档看起来比较简单因为只是需要读取两个坐标位置的文本内容而且位置相对固定。所以就直接用java的第三方库pdfbox来操作PDF文档。
2. 找个能操作PDF的第三方库pdfbox。
先下载pdfbox的jar包。 官网介绍 pdfbox能干啥 pdfbox是Apache软件基金会的一个开源项目它提供API和工具来处理PDF文档。 pdfbox是Apache PDFBox的Java版本它提供了一个类库用于读取写入转换和创建PDF文档。 pdfbox支持处理各种PDF特性如文本字体图像表单字段注释书签页面布局等。 pdfbox还提供了对加密和数字签名PDF文档的支持以及对PDF文档的提取和合并。 pdfbox还提供了对PDF文档的验证签名验证加密验证和数字签名的支持。 PDFBox是一个用于处理PDF文档的Java库。它提供了一组功能强大的API可以用于创建、修改和提取PDF文档的内容。PDFBox可以用于各种用途包括生成PDF文档、提取文本和图像、合并和拆分PDF文件、添加水印和书签等。 PDFBox支持处理各种PDF特性如文本、字体、图像、表单字段、注释、书签、页面布局等。它还提供了对加密和数字签名PDF文档的支持以及对PDF文档的高级操作如提取文本位置信息、提取图像和字体等。
3. maven加载包 pdfbox有三个大的版本每个版本差异较大这个时候如果要引入的时候要注意对应的版本了否则demo就有可能跑不起来。pdfbox最新的大版本是3.0。作为新时代的青年肯定要与时俱进。3.0肯定是要用上的。3. 先验证下第三方库是否可行
下载jar包后直接用java代码跑下demo。 demo读取pdf文档内容并输出文本数据到控制台 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();}}
发现demo跑起来后报错。 原因是因为demo是2.0的版本而当前的jar包是3.0的版本。PDDocument.load这个修改为Loader.load就OK了。
接下来就是如何获取到指定坐标位置的文本内容。
4. 确认文本在PDF文档中的坐标位置。
确认PDF文本坐标一般有两种方案。
1. 代码校验最精准
先用demo跑下看下是否可以读取到指定坐标位置的文本内容。 /*** 获取文档坐标* 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() {Overrideprotected void writeString(String text, ListTextPosition 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后发现可以读取到指定坐标位置的文本内容。 这里会有个小问题就是返回的坐标点有的会有小数。因为当前返回类型float所以需要转换成int。
2. 最直接粗暴的方法。 1. 福昕PDF文档工具。2. 直接用福昕PDF文档定位工具定位坐标。说实话开发比较少用这种方式因为感觉有点lower(其实是自己不太会用)5. 整个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();}}结果能够正常输出对应的文本内容。
6. 整活上代码。
奉上全部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 {//要匹配的位置内容点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()) {ListMapString,Object mps listPdfFiles(folder);excelWriter.write(mps, true);} else {System.out.println(Invalid folder path.);}excelWriter.close();}/*** 获取pdf文件列表** param folder 文件夹* return {code ListMapString,Object}*/private static ListMapString,Object listPdfFiles(File folder) {ListMapString,Object mps new ArrayList();File[] files folder.listFiles();if (files ! null) {for (File file : files) {if (file.isDirectory()) {listPdfFiles(file); // 递归调用处理子文件夹} else {String fileName file.getName();if (fileName.toLowerCase().endsWith(.pdf)) {mps.add(getLineData(file));}}}}return mps;}/*** 行数据** param file 文件* return {code MapString,Object}*/public static MapString,Object getLineData(File file){MapString,Object lineData new HashMap(target.length2);ListPoint pointList getPoint(file);String[] arr getPointValue(file, pointList.stream().map(s - new Rectangle(s.getX(), s.getY(), 260, 10)).toArray(Rectangle[]::new));if(arr.lengthtarget.length) {for(int i0;itarget.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 regionNamerectangle.getX()rectangle.getY();textStripper.addRegion(regionName, rectangle);PDPage page document.getPage(0);textStripper.extractRegions(page);// 获取区域的textString text textStripper.getTextForRegion(regionName);text text.replace(\u0000,-).replace( ,);System.out.println(texttext);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 ListPoint getPoint( File file){ListPoint pointListnew ArrayList();try {PDDocument document Loader.loadPDF(file);PDFTextStripper textStripper new PDFTextStripper() {Overrideprotected void writeString(String text, ListTextPosition 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;}
}
7. 验证代码可行性
整理出来的excel检查里面有些空格没有处理就让业务自己批量替换一下。 因为代码只是一次性用的就没有怎么进行封装了。总体来讲业务同事比较满意。
结论
第三方库pdfbox可以操作PDF文档。3.0版本之后和历史版本相差比较大最好先阅读下源码。坐标定位的话可以用第三方也可以代码定位如果代码后续想复用的话最好抽离出公共方法文件比较多的情况下建议增加多线程处理。