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文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM