Java學(xué)習(xí)

          java,spring,structs,hibernate,jsf,ireport,jfreechart,jasperreport,tomcat,jboss -----本博客已經(jīng)搬家了,新的地址是 http://www.javaly.cn 如果有對(duì)文章有任何疑問(wèn)或者有任何不懂的地方,歡迎到www.javaly.cn (Java樂(lè)園)指出,我會(huì)盡力幫助解決。一起進(jìn)步

           

          pdfbox處理pdf文檔

           

          在本書(shū)的前面所介紹的內(nèi)容中,所處理的都是純文本文件。但是事實(shí)上,人們用于保存信息的文件并不是純文本格式。現(xiàn)在比較流行的文件存儲(chǔ)格式有Adobe公司的PDF和Microsoft的Word、Excel等。在處理這些文件的時(shí)候,不能簡(jiǎn)單的從文件讀取字符,需要根據(jù)他們特殊的格式提取內(nèi)容。本章就將對(duì)比較流行的PDF、Word和Excel格式的處理工具逐一進(jìn)行介紹。

          7.1 使用PDFBox處理PDF文檔

          PDF全稱Portable Document Format,是Adobe公司開(kāi)發(fā)的電子文件格式。這種文件格式與操作系統(tǒng)平臺(tái)無(wú)關(guān),可以在Windows、Unix或Mac OS等操作系統(tǒng)上通用。

          PDF文件格式將文字、字型、格式、顏色及獨(dú)立于設(shè)備和分辨率的圖形圖像等封裝在一個(gè)文件中。如果要抽取其中的文本信息,需要根據(jù)它的文件格式來(lái)進(jìn)行解析。幸好目前已經(jīng)有不少工具能幫助我們做這些事情。

          7.1.1 PDFBox的下載

          最常見(jiàn)的一種PDF文本抽取工具就是PDFBox了,訪問(wèn)網(wǎng)址http://sourceforge.net/projects/pdfbox/,進(jìn)入如圖7-1所示的下載界面。

          圖7-1 PDFBox的下載頁(yè)面

          讀者可以在該網(wǎng)頁(yè)下載其最新的版本。本書(shū)采用的是PDFBox-0.7.3版本。PDFBox是一個(gè)開(kāi)源的Java PDF庫(kù),這個(gè)庫(kù)允許你訪問(wèn)PDF文件的各項(xiàng)信息。在接下來(lái)的例子中,將演示如何使用PDFBox提供的API,從一個(gè)PDF文件中提取出文本信息。

          7.1.2 在Eclipse中配置

          以下是在Eclipse中創(chuàng)建工程,并建立解析PDF文件的工具類的過(guò)程。

          (1)在Eclipse的workspace中創(chuàng)建一個(gè)普通的Java工程:ch7。

          (2)把下載的PDFBox-0.7.3.zip解壓,解壓后的目錄結(jié)構(gòu)如圖7-2所示。

          圖7-2 解壓后的PDFBox包

          (3)進(jìn)入external目錄下,可以看到,這里包括了PDFBox所有用到的外部包。復(fù)制下面的Jar包到工程ch7的lib目錄下(如還未建立lib目錄,則先創(chuàng)建一個(gè))。

          l bcmail-jdk14-132.jar

          l bcprov-jdk14-132.jar

          l checkstyle-all-4.2.jar

          l FontBox-0.1.0-dev.jar

          l lucene-core-2.0.0.jar

          然后再?gòu)腜DFBox的lib目錄下,復(fù)制PDFBox-0.7.3.jar到工程的lib目錄下。

          (4)在工程上單擊右鍵,在彈出的快捷菜單中選擇“Build Path->Config Build Path->Add Jars”命令,把工程lib目錄下面的包都加入工程的Build Path。筆者機(jī)器上完整的工程目錄如圖7-3所示:

          圖7-3 工程截圖

          7.1.3 使用PDFBox解析PDF內(nèi)容

          在剛剛創(chuàng)建的Eclipse工程中,創(chuàng)建一個(gè)ch7.pdfbox包,并創(chuàng)建一個(gè)PdfboxTest類。該類包含一個(gè)getText方法,用于從一個(gè)PDF中獲取文本信息,其代碼如下。

          代碼7.1

          public void geText(String file) throws Exception {

          // 是否排序

             boolean sort = false;

          // pdf文件名

             String pdfFile = file;

          // 輸入文本文件名稱

             String textFile = null;

          // 編碼方式

             String encoding = "UTF-8";

          // 開(kāi)始提取頁(yè)數(shù)

             int startPage = 1;

          // 結(jié)束提取頁(yè)數(shù)

             int endPage = Integer.MAX_VALUE;

          // 文件輸入流,生成文本文件

             Writer output = null;

          // 內(nèi)存中存儲(chǔ)的PDF Document

             PDDocument document = null;

          try {

                try {

                   // 首先當(dāng)作一個(gè)URL來(lái)裝載文件,如果得到異常再?gòu)谋镜匚募到y(tǒng)//去裝載文件

                   URL url = new URL(pdfFile);

                   document = PDDocument.load(url);

                   // 獲取PDF的文件名

                   String fileName = url.getFile();

                  

          // 以原來(lái)PDF的名稱來(lái)命名新產(chǎn)生的txt文件

                   if (fileName.length() > 4) {

                      File outputFile = new File(fileName.substring(0, fileName.length() - 4) + ".txt");

                      textFile = outputFile.getName();

                   }

                } catch (MalformedURLException e) {

                  

          // 如果作為URL裝載得到異常則從文件系統(tǒng)裝載

                   document = PDDocument.load(pdfFile);

                   if (pdfFile.length() > 4) {

                      textFile = pdfFile.substring(0, pdfFile.length() - 4) + ".txt";

                   }

                }

                // 文件輸入流,寫(xiě)入文件倒textFile

                output = new OutputStreamWriter(new FileOutputStream(textFile), encoding);

                // PDFTextStripper來(lái)提取文本

                PDFTextStripper stripper = null;

                stripper = new PDFTextStripper();

          // 設(shè)置是否排序

                stripper.setSortByPosition(sort);

          // 設(shè)置起始頁(yè)

                 stripper.setStartPage(startPage);

          // 設(shè)置結(jié)束頁(yè)

                stripper.setEndPage(endPage);

          // 調(diào)用PDFTextStripper的writeText提取并輸出文本

                stripper.writeText(document, output);

             } finally {

                if (output != null) {

                   // 關(guān)閉輸出流

                   output.close();

                }

                if (document != null) {

                   // 關(guān)閉PDF Document

                   document.close();

                }

             }

          }

          在上面的代碼中,getText方法接收一個(gè)String類型的參數(shù),指定要提取的PDF文件路徑。這個(gè)位置可以是一個(gè)URL或本地文件。然后函數(shù)調(diào)用PDFBox提供的PDFTextStripper類,設(shè)置提取過(guò)程中的一些屬性(如起始頁(yè)、是否排序等)。最后將文本提取并寫(xiě)入文件。

          7.1.4 運(yùn)行效果

          下面看一下這個(gè)函數(shù)的運(yùn)行效果,在PdfboxTest加入一個(gè)main函數(shù),其代碼如下。

          public static void main(String[] args) {

             PdfboxTest test = new PdfboxTest();

             try {

                // 取得C盤(pán)下的index.pdf的內(nèi)容

                test.geText("C:\\index.pdf");

             } catch (Exception e) {

                e.printStackTrace();

             }

          }

          這里要處理一個(gè)index.pdf文件,該P(yáng)DF文件的內(nèi)容如圖7-4所示。

          圖7-4 要解析的PDF文檔內(nèi)容

          通過(guò)PdfboxTest處理后的文本文件如圖7-5所示。

          圖7-5 處理的結(jié)果

          可以看到,PDF中的文本已經(jīng)被提取出來(lái),保存于文本文件中了。其中第4行的超鏈接部分“POI News WebBlog”,在文本文件中已經(jīng)被替換成了普通的純文本。讀者可以根據(jù)PDFBox所提供的API文檔進(jìn)一步查詢其他功能。

          7.1.5 與Lucene的集成

          PDFBox還提供和Lucene的集成,它提供了一套簡(jiǎn)單的方法把PDF Documents加入到Lucene的索引中去,請(qǐng)看以下代碼:

          Document lucenedocument = LucenePDFDocument.getDocument(…);

          其中,LucenePDFDocument是PDFBox中提供的一個(gè)類,它的getDocument被重載為3個(gè)方法,分別接收一個(gè)File對(duì)象、InputStream對(duì)象或者URL對(duì)象作為參數(shù),然后從該參數(shù)傳遞進(jìn)來(lái)的PDF文件中,提取并生成Lucene的Document對(duì)象。

          當(dāng)通過(guò)PDFBox從一個(gè)PDF文檔中得到一個(gè)Lucene Document后,可以直接使用IndexWriter把它加到Lucene的index中。LucenePDFDocument自動(dòng)從PDF文件中提取各種元數(shù)據(jù)Field,并把它們加入到Document中。它提取的信息如表7-1所示。

          表7-1 PDFBox生成的Lucene Document格式

          Lucene Field名稱

          說(shuō)明

          path

          文件系統(tǒng)路徑(如果文檔是從文件裝載)

          url

          URL地址(如果文檔是從網(wǎng)絡(luò)裝載)

          contents

          整個(gè)Document的內(nèi)容,索引但不存儲(chǔ)

          summary

          Document的內(nèi)容前500個(gè)字符

          modified

          最后修改時(shí)間

          uid

          Document的惟一ID

          CreationDate

          從PDF的meta-data獲取

          Creator

          從PDF的meta-data獲取

          Keywords

          從PDF的meta-data獲取

          ModificationDate

          從PDF的meta-data獲取

          Producer

          從PDF的meta-data獲取

          Subject

          從PDF的meta-data獲取

          Trapped

          從PDF的meta-data獲取

          下面通過(guò)LucenePDFDocument,直接對(duì)PDF建立索引,在ch7.pdfbox包下面新建一個(gè)PdfLuceneTest類,該類的代碼如下。

          代碼7.2

          public class PdfLuceneTest {

              public static void main(String[] args) {

                  try {

                      // IndexWriter存放索引到d:\index下

                      IndexWriter writer = new IndexWriter("d:\\index",

                              new StandardAnalyzer(), true);

                      // LucenePDFDocument返回由PDF產(chǎn)生的Lucene Docuement

                      Document d = LucenePDFDocument

                              .getDocument(new File("C:\\index.pdf"));

                      // 寫(xiě)入索引

                      writer.addDocument(d);

                      // 關(guān)閉索引文件流

                      writer.close();

                      // 讀取d:\index下的索引文件建立IndexSearcher

                      IndexSearcher searcher = new IndexSearcher("d:\\index");

                      // 對(duì)索引的contents Field進(jìn)行查找關(guān)鍵詞poi

                      Term t = new Term("contents", "poi");

                      // 根據(jù)Term生成Query

                      Query q = new TermQuery(t);

                      // 搜索返回結(jié)果集

                      Hits hits = searcher.search(q);

                      // 打印結(jié)果集

                      for (int i = 0; i < hits.length(); i++) {

                          System.out.println(hits.doc(i));

                      }

                  } catch (Exception e) {

                      e.printStackTrace();

                  }

              }

          }

          函數(shù)利用LucenePDFDocument的getDocument函數(shù),從一個(gè)PDF文件直接返回一個(gè)Lucene的Document,其中包含有path、url、modified、contents、summary等Field,把它們直接寫(xiě)入index,然后創(chuàng)建一個(gè)IndexSearcher,對(duì)contents字段經(jīng)行檢索,查找關(guān)鍵詞“poi”(注意必須是小寫(xiě)),程序的執(zhí)行結(jié)果如圖7-6所示。

          圖7-6 搜索代碼的運(yùn)行結(jié)果

          posted on 2009-06-11 16:25 找個(gè)美女做老婆 閱讀(7726) 評(píng)論(1)  編輯  收藏

          評(píng)論

          # re: pdfbox處理pdf文檔 2015-12-12 15:46 toria

          Exception in thread "main" java.lang.NullPointerException
          at org.fontbox.afm.AFMParser.main(AFMParser.java:318)  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          本blog已經(jīng)搬到新家了, 新家:www.javaly.cn
           http://www.javaly.cn

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 迁安市| 马尔康县| 谢通门县| 徐汇区| 德化县| 五大连池市| 苗栗市| 金秀| 柘城县| 九台市| 耒阳市| 南充市| 丹巴县| 县级市| 鹤庆县| 蓝山县| 雅江县| 滨州市| 枣庄市| 汨罗市| 嵊州市| 张家港市| 敖汉旗| 堆龙德庆县| 洪雅县| 满城县| 榆中县| 宜春市| 博乐市| 崇仁县| 稻城县| 土默特左旗| 扎囊县| 大化| 响水县| 阳东县| 富川| 吉木乃县| 城市| 鄂托克前旗| 监利县|