zoukankan      html  css  js  c++  java
  • Java文件操作系列[1]——PDFBox实现分页提取PDF文本

    需求:用java分页提取PDF文本。

    PDFBox是一个很好的可以满足上述需求的开源工具。

    1.PDF文档结构

    要解析PDF文本,我们首先要了解PDF文件的结构。

    关于PDF文档,最重要的几点:

    一,PDF文档内容比较复杂,比如有纯文本(可以提取出其中的文字,可以用PDF软件中的“复制”功能)、图片(无法使用PDF软件中的“复制”功能)、表单、视频、音频等,总之形式比较复杂;

    二,PDF文件采用二进制流与纯文字混合的编码模式,并且没有采用 Unicode 等标准字符编码方式,其字符编码采用 Adobe 公司内建的编码表( CMap),这使得对 PDF 的处理更加困难;

    三,PDF有自己的文件结构:文件头,对象集合,交叉引用表,结尾(准确地说,这是PDF文档的物理结构,还有逻辑结构,详情可以点击查看这篇博文)。

    2.PDFBox是个什么玩意

    3.PDFBox能干啥

    • 从PDF提取文本
    • 合并PDF文档
    • PDF 文档加密与解密
    • 与Lucene搜索引擎的集成
    • 填充PDF/XFDF表单数据
    • 从文本文件创建PDF文档
    • 从PDF页面创建图片
    • 打印PDF文档

    4.准备工作

    再次声明,本demo功能是提取PDF文本(中文文本验证也通过)。

    1) 下载好jar包(3个):

    a.fontbox-2.0.0-RC2.jar

    b.pdfbox-2.0.0-RC2.jar

    c.pdfbox-app-2.0.0-RC2.jar

    下载地址1:我的下载

    下载地址2:官网下载

    2) myeclipse或eclipse。

    5.开始编程

    新建一个项目,写入下面的源码:

      1 package com.primeton.pdfbox;
      2 
      3 import java.io.File;
      4 import java.io.FileOutputStream;
      5 import java.io.OutputStreamWriter;
      6 import java.io.Writer;
      7 
      8 import org.apache.pdfbox.pdmodel.PDDocument;
      9 import org.apache.pdfbox.text.PDFTextStripper;
     10 
     11 
     12 /**
     13  * PDFBox解析PDF文本实现
     14  * @author MrChen
     15  *
     16  */
     17 
     18 public class PDFReader {
     19     /**
     20       * @param args
     21       */
     22      public static void main(String[] args) {
     23       // TODO Auto-generated method stub
     24       PDFReader pdfReader = new PDFReader();
     25       System.out.println("E:\AndroidStudio.pdf");
     26       try {
     27            // 取得E盘下的SpringGuide.pdf的内容
     28            System.out.println("开始提取");
     29            File file = new File("E:\AndroidStudio.pdf");
     30            System.out.println("文件绝对路径为:"+file.getAbsolutePath());
     31            pdfReader.readFdf(file);
     32            System.out.println("提取结束");
     33       } catch (Exception e) {
     34            e.printStackTrace();
     35       }
     36      }
     37      
     38      public void readFdf(File pdfFile) throws Exception {
     39           // 是否排序
     40           boolean sort = false;
     41           // 输入文本文件名称
     42           String textFileName = null;
     43           // 编码方式
     44           String encoding = "UTF-8";
     45           // 开始提取页数
     46           int startPage = 1;
     47           // 结束提取页数
     48           int endPage = 3;
     49           // 文件输入流,生成文本文件
     50           Writer output = null;
     51           // 内存中存储的PDF Document
     52           PDDocument document = null;
     53           
     54           File outputFile = null;
     55           try {
     56          
     57                // 从本地装载文件
     58                //注意参数已不是以前版本中的URL.而是File。
     59                 System.out.println("开始装载文件"+pdfFile.getName());
     60                 document = PDDocument.load(pdfFile);
     61                 if (pdfFile.getName().length() > 4) {
     62                     textFileName = pdfFile.getName().substring(0, pdfFile.getName().length() - 4) + ".txt";
     63                     outputFile = new File(pdfFile.getParent(),textFileName);
     64                     System.out.println("新文件绝对路径为:"+outputFile.getAbsolutePath());
     65                     
     66                  
     67                 }
     68                 System.out.println("装载文件结束");
     69  
     70            
     71                System.out.println("开始写到txt文件中");
     72                // 文件输入流,写入文件倒textFile
     73                output = new OutputStreamWriter(new FileOutputStream(outputFile),encoding);
     74                System.out.println("写入txt文件结束");
     75                // PDFTextStripper来提取文本
     76                PDFTextStripper stripper = null;
     77                stripper = new PDFTextStripper();
     78                // 设置是否排序
     79                stripper.setSortByPosition(sort);
     80                // 设置起始页
     81                stripper.setStartPage(startPage);
     82                // 设置结束页
     83                stripper.setEndPage(endPage);
     84                // 调用PDFTextStripper的writeText提取并输出文本
     85                System.out.println("开始调用writeText方法");
     86                stripper.writeText(document, output);
     87                System.out.println("调用writeText方法结束");
     88           }catch (Exception e) {
     89                e.printStackTrace();
     90           }finally {
     91               if (output != null) {
     92                     // 关闭输出流
     93                     output.close();
     94                }
     95                if (document != null) {
     96                 // 关闭PDF Document
     97                 document.close();
     98                }
     99           }
    100      }
    101 }
    解析PDF文本

    有很多打桩的语句,可以自行去除。

    同时,本程序也可以提取中文信息。

    6.遇到的问题及解决方案

    1)一开始使用的并不是PDFBox2.0版本,而是1.8版(2.0版本还是实验版本,故选用了早期的1.8版本)。但选择1.8版本,使用PDDocument.load(String)方法时,老是出现这个异常——“java.io.IOException: Push back buffer is full”。

    解决方案:上述问题困扰了笔者很久。笔者为此重新复习了IO和NIO的一些知识,并查阅了PDFBox英文API文档(1.8版本),均无解决思路。后大量查阅资料得知,这可能是1.8版本出现的bug,2.0版本修复了此bug。笔者将jar包改为2.0版本,果然就好了。需要提醒的是,2.0版本PDDocument.load()方法参数为File类型,不再是String类型。可以参阅官方API文档

  • 相关阅读:
    Civil 3D .NET二次开发第11章代码升级至2018版注意事项
    创建道路曲面
    ObjectARX® for Beginners: An Introduction
    mshcMigrate制作的mshc文件中有链接打不开
    Word 2013无法发布文章到博客园
    ionic 安装插件报错:源文本中存在无法识别的标记
    typescript文件中 使用回调函数无法调用函数外的变量和方法的办法
    ionic2---自定义插件
    angular2----使用swiper做轮播图
    angular2----router
  • 原文地址:https://www.cnblogs.com/helloIT/p/5074918.html
Copyright © 2011-2022 走看看