1. 程式人生 > >7.2 使用xpdf來處理中文PDF文件

7.2 使用xpdf來處理中文PDF文件

7.2  使用xpdf來處理中文PDF文件

PDFBox看起來非常的方便,它的API功能強大。甚至能和Lucene進行無縫的結合。但是它有一個致命的弱點,就是它不支援中文。要提取中文的文字,可以採用另一個非常出色的工具xpdf。

7.2.1  xpdf的下載

讀者可以到http://www.foolabs.com/xpdf/download.html下載最新版本的xpdf。如圖7-7所示。

圖7-7  xpdf的下載頁面

本書採用的是xpdf-3.01pl2-win32.zip。另外,還需要下載一箇中文包xpdf-chinese-simplified.tar.gz。

7.2.2  配置

將xpdf-3.01pl2-win32.zip解壓到c:/xpdftest目錄下,然後將xpdf-chinese-simplified.tar.gz解壓倒c:/xpdftest/xpdf/目錄下,解壓後的目錄結構如圖7-8所示。

圖7-8  Xpdf解壓後的目錄

開啟目錄下的xpdfrc檔案,編輯檔案內容,如下程式碼所示。

程式碼7.3

cidToUnicode    Adobe-GB1       c:/xpdftest/xpdf/xpdf-chinese-simplified/Adobe-GB1.cidToUnicode

unicodeMap      ISO-2022-CN     c:/xpdftest/xpdf/xpdf-chinese-simplified/ISO-2022-CN.unicodeMap

unicodeMap      EUC-CN          c:/xpdftest/xpdf/xpdf-chinese-simplified/EUC-CN.unicodeMap

unicodeMap  GBK     c:/xpdftest/xpdf/xpdf-chinese-simplified/GBK.unicodeMap

cMapDir         Adobe-GB1       c:/xpdftest/xpdf/xpdf-chinese-simplified/CMap

toUnicodeDir                    c:/xpdftest/xpdf/xpdf-chinese-simplified/CMap

fontDir C:/WINDOWS/Fonts

displayCIDFontTT Adobe-GB1 C:/WINDOWS/Fonts/simhei.ttf

textEOL      CR+LF

檔案的路徑讀者可以根據自己的環境改,如在windows 2000下,fontDir所在的位置是C:/WINNT/Fonts,displayCIDFontTT Adobe-GB1的位置是在C:/WINNT/Fonts/simhei.ttf。

7.2.3  提取中文

在工程中新建一個ch7.xpdf包,並建立一個Pdf2Text類。該類採用Runtime傳入引數,呼叫pdftotext.exe來進行文字的提取。其具體實現程式碼如下。

程式碼7.4

public class Pdf2Text {

    // PDF檔名

    private File pdffile;

    // 轉換器的存放位置,預設在c:/xpdf下面

    private String CONVERTOR_STORED_PATH = "c://xpdf";

    // 轉換器的名稱,預設為pdftotext

    private String CONVERTOR_NAME = "pdftotext";

    // 建構函式,引數為pdf檔案的路徑

    public Pdf2Text(String pdffile) throws IOException {

        this(new File(pdffile));

    }

    // 建構函式,引數為pdf檔案的對像

    public Pdf2Text(File pdffile) throws IOException {

        this.pdffile = pdffile;

    }

    // 將pdf轉為文字文件

    public void toTextFile() throws IOException {

        toTextFile(pdffile, true);

    }

    // 將pdf轉為文字文件,引數為目標檔案的路徑,預設使用PDF檔案中的佈局

    public void toTextFile(String targetfile) throws IOException {

        toTextFile(new File(targetfile), true);

    }

    // 將pdf轉為文字文件,引數1為目標檔案的路徑,

    // 引數2為true則表示使用PDF檔案中的佈局

    public void toTextFile(String targetfile, boolean isLayout)

            throws IOException {

        toTextFile(new File(targetfile), isLayout);

    }

    // 將pdf轉為文字文件,引數為目標檔案

    public void toTextFile(File targetfile) throws IOException {

        toTextFile(targetfile, true);

    }

    // 將pdf轉為文字文件,引數1為目標檔案,

    // 引數2為true則表示使用PDF檔案中的佈局

    public void toTextFile(File targetfile, boolean isLayout)

            throws IOException {

        String[] cmd = getCmd(targetfile, isLayout);

        Process p = Runtime.getRuntime().exec(cmd);

    }

    // 獲取PDF轉換器的路徑

    public String getCONVERTOR_STORED_PATH() {

        return CONVERTOR_STORED_PATH;

    }

    // 設定PDF轉換器的路徑

    public void setCONVERTOR_STORED_PATH(String path) {

        if (!path.trim().endsWith("//"))

            path = path.trim() + "//";

        this.CONVERTOR_STORED_PATH = path;

    }

    // 解析命令列引數

    private String[] getCmd(File targetfile, boolean isLayout) {

        // 命令字元

        String command = CONVERTOR_STORED_PATH + CONVERTOR_NAME;

        // PDF檔案的絕對路徑

        String source_absolutePath = pdffile.getAbsolutePath();

        // 輸出文字檔案的絕對路徑

        String target_absolutePath = targetfile.getAbsolutePath();

        // 保持原來的layout

        String layout = "-layout";

        // 設定編碼方式

        String encoding = "-enc";

        String character = "GBK";

        // 設定不列印任何訊息和錯誤

        String mistake = "-q";

        // 頁面之間不加入分頁

        String nopagebrk = "-nopgbrk";

        // 如果isLayout為false,則設定不保持原來的layout

        if (!isLayout)

            layout = "";

        return new String[] { command, layout, encoding, character, mistake,

                nopagebrk, source_absolutePath, target_absolutePath };

    }

}

該類對外提供一個toTextFile()方 法。該方法接收2個引數:targetfile為目標PDF檔案,isLayout表示是否採用原始的PDF檔案中的layout佈局。類中的 getCmd()方法負責解析傳進來的引數,並生成一個String陣列。該String陣列表示一個作業系統中的命令,其中,各項分別代表命令後所跟的 引數。在獲得到該陣列後,再呼叫Runtime.getRuntime().exec(String[])函式來執行命令。

注意:在getCmd()方法中設定編碼方式的 時候,用到的是GBK。這並不是對所有的檔案都適用,因為中文的編碼方式不只一種,讀者可以根據PDF的編碼型別選擇不同的encoding方式。所有簡 體中文的編碼方式都定義在檔案xpdfrc中的unicodeMap中,現在支援3種編碼方式,分別是ISO-2022-CN,EUC-CN,GBK,如 圖7-9所示。

圖7-9  xpdfrc檔案的內容

7.2.4  執行效果

下面通過一個函式來測試Pdf2Text類,在ch7.xpdf包中新建一個Pdf2TextTest類,包含一個main函式,其程式碼如下。

程式碼7.5

public class Pdf2TextTest {

    public static void main(String[] args) {

        try {

            // 引數輸入PDF檔案的存放位置

            Pdf2Text p2t = new Pdf2Text("c://test.pdf");

            // 設定轉換器的位置

            p2t.setCONVERTOR_STORED_PATH("c://xpdftest//xpdf");

            // 設定文字檔案存放位置

            p2t.toTextFile("c://test.txt");

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

用於轉換的PDF檔案如圖7-10所示。

圖7-10  用於轉換的中文PDF檔案

程式碼7.5執行之後,結果如圖7-11所示。

圖7-11  執行結果