图片型pdf转文本文档
基本思路
直接用工具将扫描型pdf转文本是不行的,因为扫描型的pdf是图片。先读取整个pdf文件按页生成图片,在调用OCR识别读取文字即可。
pdf第三方库pdfbox
依赖:
<!--pdfbox pdf解析--><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.1</version></dependency>
使用该库可对pdf文件进行基本读写操作
File file = new File(PdfFilePath);
//加载pdf,可对其进行基本读写
PDDocument pdDocument = PDDocument.load(file);
int pages =pdDocument.getNumberOfPages();// 获取PDF页数
//pdf renderer 渲染器,可转成图片读取
PDFRenderer renderer = new PDFRenderer(pdDocument);
BufferedImage image = renderer.renderImageWithDPI(i, dpi);//i为页数,dpi为精度,默认96
从pdf中读取文本
/*** 指定pdf与目标文件路径,从pdf文件读取文本到指定文件* @param pdfPath pdf文件路径,绝对路径* @param targetPath 目标文件,绝对路径*/public static void readTextFromPdf(String pdfPath,String targetPath) {//pdf文件校验File pdfFile=new File(pdfPath);if(!pdfFile.exists()){System.out.println("pdf文件未发现:"+pdfPath);return;}File targetFile=new File(targetPath);PDDocument pdDocument=null;try{//读取文档pdDocument=PDDocument.load(pdfFile);//获取文档页码int pages=pdDocument.getNumberOfPages();//读取文档内容并设置读取参数PDFTextStripper stripper=new PDFTextStripper();stripper.setSortByPosition(true);stripper.setStartPage(1);stripper.setEndPage(pages);String content=stripper.getText(pdDocument);//校验目标文件if(targetFile.exists()){System.out.println("文件已存在,将覆盖文件");}else {System.out.println("目标文件不存在,新建文件");targetFile.createNewFile();}//写入目标文件FileWriter fileWriter=new FileWriter(targetFile);fileWriter.write(content);}catch (Exception e){e.printStackTrace();}System.out.println("写入文件成功");}
将pdf转换为图片
/*** PDF文件转PNG/JPEG图片* @param PdfFilePath 完整路径* @param dstImgFolder 图片存放的文件夹* @param dpi dpi越大转换后越清晰,相对转换速度越慢,一般电脑默认96dpi*/public static void pdf2Image(String PdfFilePath,String dstImgFolder,int dpi) {File file = new File(PdfFilePath);PDDocument pdDocument;try {//获取pdf文件名称与上层路径String imgPDFPath = file.getParent();int dot = file.getName().lastIndexOf('.');// 获取图片文件名String imagePDFName = file.getName().substring(0, dot);String imgFolderPath = null;if (dstImgFolder.equals("")) {// 获取图片存放的文件夹路径imgFolderPath = imgPDFPath + File.separator + imagePDFName;} else {imgFolderPath = dstImgFolder + File.separator + imagePDFName;}if (createDirectory(imgFolderPath)) {pdDocument = PDDocument.load(file);PDFRenderer renderer = new PDFRenderer(pdDocument);int pages =pdDocument.getNumberOfPages();// 获取PDF页数System.out.println("PDF page number is:" + pages);StringBuffer imgFilePath = null;for (int i = 0; i < pages; i++) {String imgFilePathPrefix = imgFolderPath+ File.separator + imagePDFName;imgFilePath = new StringBuffer();imgFilePath.append(imgFilePathPrefix);imgFilePath.append("_");imgFilePath.append(String.valueOf(i + 1));imgFilePath.append(".png");// PNGFile dstFile = new File(imgFilePath.toString());BufferedImage image = renderer.renderImageWithDPI(i, dpi);ImageIO.write(image, "png", dstFile);// PNG}System.out.println("PDF文档转PNG图片成功!");} else {System.out.println("PDF文档转PNG图片失败:"+ "创建" + imgFolderPath + "失败");}} catch (IOException e) {e.printStackTrace();}}private static boolean createDirectory(String folder) {File dir = new File(folder);if (dir.exists()) {return true;} else {return dir.mkdirs();}}
使用百度API进行OCR识别
登录百度AI开放平台,选择文字识别→通用文字识别
选择文字识别创建应用,三个用于权鉴的必要参数:AppID,AppKey,SecretKey
官方文档:百度AI文字识别文档
请注意不同的场景的免费额度限制
权鉴获取token
/*** @Author lsl* @Date 2020/12/15 9:00** 百度API OCR 文字识别客户端* 用于配置权鉴认证*/
public abstract class ApiOcrClient {//设置APPID/AK/SK,注意替换为自己的public static final String APP_ID = "2**...";// 官网获取的 API Key 更新为你注册的public static final String API_KEY = "i**...";// 官网获取的 Secret Key 更新为你注册的public static final String SECRET_KEY = "**...";//标准版通用文字识别,50000次/天public static final String GENERAL_BASIC_URL="https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic";/*** 子类可使用的客户端,用于连接*/protected static AipOcr client=new AipOcr(APP_ID, API_KEY, SECRET_KEY);/*** 获取权限token* @return 返回示例:* {* "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",* "expires_in": 2592000* }*/public static String getAuth() {return getAuth(API_KEY, SECRET_KEY);}/*** 获取API访问token* 该token有一定的有效期,需要自行管理,当失效时需重新获取.* @param ak - 百度云官网获取的 API Key* @param sk - 百度云官网获取的 Securet Key* @return assess_token 示例:* "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"*/public static String getAuth(String ak, String sk) {// 获取token地址String authHost = "https://aip.baidubce.com/oauth/2.0/token?";String getAccessTokenUrl = authHost// 1. grant_type为固定参数+ "grant_type=client_credentials"// 2. 官网获取的 API Key+ "&client_id=" + ak// 3. 官网获取的 Secret Key+ "&client_secret=" + sk;try {URL realUrl = new URL(getAccessTokenUrl);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();connection.setRequestMethod("GET");connection.connect();// 获取所有响应头字段Map<String, List<String>> map = connection.getHeaderFields();// 遍历所有的响应头字段for (String key : map.keySet()) {System.err.println(key + "--->" + map.get(key));}// 定义 BufferedReader输入流来读取URL的响应BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));StringBuilder result = new StringBuilder();String line;while ((line = in.readLine()) != null) {result.append(line);}/*** 返回结果示例*/System.err.println("result:" + result);JSONObject jsonObject = new JSONObject(result.toString());return jsonObject.getString("access_token");} catch (Exception e) {System.err.print("获取token失败!");e.printStackTrace(System.err);}return null;}
}
文字识别返回结果
/*** @Author lsl* @Date 2020/11/9 13:49** 百度API文字识别返回响应,返回数据以行为单位*/
public class ApiOcrRes {private String logId;/** 返回结果集,wordResult代表一行 */private List<WordResult> wordsResult;/** 行数 */private int wordsResultNum;public String getLogId() {return logId;}public void setLogId(String logId) {this.logId=logId;}public List<WordResult> getWordsResult() {return wordsResult;}public void setWordsResult(List<WordResult> wordsResult) {this.wordsResult=wordsResult;}public int getWordsResultNum() {return wordsResultNum;}public void setWordsResultNum(int wordsResultNum) {this.wordsResultNum=wordsResultNum;}
}
/*** 每行识别结果*/
class WordResult{private String words;public String getWords() {return words;}public void setWords(String words) {this.words = words;}
}
识别图片
注意要继承上面的抽象父类以获取token
/*** 百度AI OCR文字识别,注意每天访问次数与accessToken过期时间* @param imgPath 本地图片路径* @param url 百度API URL* @param accessToken 百度API 访问Token* @return 识别结果*/
public static String baiduAiOcrGeneralBasic(String imgPath,String url,String accessToken) {try {/*** 重要提示代码中所需工具类* FileUtil,Base64Util,HttpUtil,GsonUtils请从* https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72* https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2* https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3* https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3* 下载*/byte[] imgData = FileUtil.readFileByBytes(imgPath);String imgStr = Base64Util.encode(imgData);String imgParam = URLEncoder.encode(imgStr, "UTF-8");String param = "image=" + imgParam;//发起请求String result = HttpUtil.post(url, accessToken, param);//JSON转换ApiOcrRes apiOcrRes = JSON.parseObject(result, ApiOcrRes.class);StringBuilder res=new StringBuilder();System.out.println("识别结果行数:"+apiOcrRes.getWordsResultNum());if(apiOcrRes.getWordsResult()!=null){for (WordResult words : apiOcrRes.getWordsResult()) {res.append(words.getWords()).append("\n");}}return res.toString();} catch (Exception e) {e.printStackTrace();}return null;
}/*** 将指定图片文件转换成文本并返回字符串* 带位置高精度识别,访问次数500/天** @param imgPath 图片文件* @return 识别结果*/
public static String ImgToText(String imgPath) {if (imgPath == null || imgPath.length() == 0 || !new File(imgPath).exists() || !new File(imgPath).isFile()) {System.out.println("文件不存在");return "";}//返回结果StringBuilder res = new StringBuilder();// 传入可选参数调用接口HashMap<String, String> options = new HashMap<>();options.put("detect_direction", "true");//ocr识别 参数为本地图片路径 获取OCR识别结果JSONObject resOcr = client.basicAccurateGeneral(imgPath, options);//JSON转换ApiOcrRes apiOcrRes = JSON.parseObject(resOcr.toString(), ApiOcrRes.class);System.out.println("识别结果:"+apiOcrRes.getWordsResultNum());if(apiOcrRes.getWordsResult()!=null){for (WordResult words : apiOcrRes.getWordsResult()) {res.append(words.getWords()).append("\n");}}return res.toString();
}
封装-识别图片目录
/*** 将指定图片目录的所有图片文件转换成文本到指定文本文件** @param imgDirPath 图片目录,按顺序识别所有图片* @param textPath 目标文本文件路径* @param comparator 比较器,目录下图片的排序规则*/
public static void ImgDirToText(String imgDirPath, String textPath, Comparator<File> comparator) {//图片目录校验File imgDir = new File(imgDirPath);if (!imgDir.exists() || !imgDir.isDirectory()) {System.out.println("错误:图片目录不存在或是文件");return;}//目标文本文件File textFile = new File(textPath);try {if (!textFile.exists() && !textFile.createNewFile()) {System.out.println("创建目标文件失败");return;}FileWriter fileWriter = new FileWriter(textFile);//遍历图片目录,按照顺序规则严格指定File[] imgFiles = imgDir.listFiles();//指定排序规则Arrays.sort(imgFiles, comparator);//获取TokenString accessToken=getAuth();for (File file : imgFiles) {System.out.println("开始将图片转换为文本:" + file.getAbsolutePath());//获取OCR识别结果String res = baiduAiOcrGeneralBasic(file.getAbsolutePath(),GENERAL_BASIC_URL,accessToken);//写入文件fileWriter.write(res);}//关闭文件fileWriter.close();} catch (Exception e) {e.printStackTrace();}
}
封装-使用测试
注意按照生成图片命名规则来构造比较器
@Testpublic void imgDirToText() {Comparator comparator=new Comparator<File>() {@Overridepublic int compare(File o1, File o2) {String a1=o1.getAbsolutePath();String a2=o2.getAbsolutePath();a1=a1.substring(a1.indexOf('_')+1,a1.indexOf('.'));a2=a2.substring(a2.indexOf('_')+1,a2.indexOf('.'));return Integer.parseInt(a1)-Integer.parseInt(a2);}};Image2Text.ImgDirToText("E:\\新建文件夹","E:\\ctf特训营1.txt",comparator);}
图片型pdf转文本文档相关推荐
- PDF文件如何转换成txt文本文档
想要将PDF文件转换成txt文本文档,需要用到PDF转换器的帮助,比如奥凯丰 PDF转换大师将PDF文件格式转换一下. [PDF转换大师]转为word_excel_ppt_txt_jpg等格式-奥凯丰 ...
- 从TXT文本文档向Sql Server中批量导入数据
因为工作的需要,近期在做数据的分析和数据的迁移.在做数据迁移的时候需要将原有的数据导入到新建的数据库中.本来这个单纯的数据导入导出是没有什么问题的,但是客户原有的数据全部都是存在.dat文件中的.所以 ...
- 如何把文本文档转换成html格式,把固定格式的文本文档转换为Excel电子表格的方法...
有时候,需要把一些拥有固定格式的文本文件导入电子表格.微软的Excel 电子表格程序有一个文本文件转换向导,将这种格式转换变得非常快捷方便.本文图文讲解把固定格式的文本文档转换为Excel电子表格的方 ...
- 如何将多个文本文档合并到一个文档中?
2019独角兽企业重金招聘Python工程师标准>>> 在日常工作中,我们需要将多个文本文档合并到一个中,接下来将介绍一种批处理的方法. 工具/原料 文本文档 方法/步骤 如图所示, ...
- win10右键新建没有文本文档
点击开始找到电脑附件,如图所示: 二.将下面代码放到文本保存为txtfile.reg 文件,保存到桌面,双击提示是否,点击就是变可以,然后你右击后你会发现你文本文档回来了 Windows Regist ...
- 新建一个文本文档,将后缀改为html,却还是文本文档格式,且后缀有txt
问题描述: 如图,在文本文档中写好网页代码,然后加后缀html,结果还是txt文档. 解决方法: 1.在文件夹点开或者直接在左下角搜索此电脑 2.点开此电脑,在顶部找到"查看".点 ...
- 《新建文本文档》贾瑜
我的笔记本电脑出了点问题,苦笑不得. 2010年花了6000元买的机器,重装了约7次系统,最后稳定在现在这个舆论口碑很差的VISTA系统.但我用了大概一年左右,再也没出过问题, 虽然慢是慢了点,好在稳 ...
- 在线文本文档txt编辑器_审查了6位在线文档和文本编辑者
在线文本文档txt编辑器 Who wants to limit himself to one computer nowadays? Say hello to online editors, where ...
- win10新建文本文档(TXT)的快捷键
默认是没有这个快捷键的,方法在这个网页:飞机票. 最后的任务计划程序部分我没有成功,最后开机会弹出注册表提示,确认就行. 以防万一我截个图防止这个网页消失 Windows Registry Edito ...
最新文章
- c++ 重载、重写、重定义(隐藏)
- 解决docker中/etc/default/docker配置DOCKER_OPTS 失效问题
- php 清除opcache缓存的方法
- echarts graph图重叠_借官方关系图尝试下屏蔽鼠标浮在 links 上弹出的提示框
- iOS研发助手DoraemonKit技术实现(一)
- phpddos***器1.0-6.0
- CMSIS-DSP lib 矩阵运算示例和源码
- 动态ARP检测原理及应用
- 内存超频时序怎么调_憋了很久的问题:内存时序有什么用?超频时怎么调?
- 基于Trie树实现拼音搜索自动补全
- JAVA并发系列十九:深入理解ThreadLocal(三)–详解ThreadLocal内存泄漏问题
- Java的第一个你好世界
- 如何下载网页中的视频成mp4格式
- Belief Propagation信念传播算法详解
- Web前端下载文件的几种常见方式
- 邮政储蓄银行厦门分行经营管理系统 项目总结
- JS实现多张图片绕中心点转动
- 《Cocos Creator游戏实战》实现下拉框按钮ComboBox控件
- 同样是IT行业,测试和开发薪资真有这么大差别?
- 编程题——Fibonacci数列