Java解析pdf獲取pdf中內容信息

java解析pdf獲取pdf中內容信息

今日項目中需要將pdf中的數據獲取到進行校驗數據,於是前往百度翻來覆去找到以下幾種辦法,做個筆記,方便日後查詢。

廢話不多說,我要直接上代碼裝逼了

第一種 使用開源組織提供的開源框架 pdfbox

api ; https://pdfbox.apache.org/

特點:免費,功能強大,解析中文或許會存在亂碼,默認格式有點亂,沒有國產解析的那麼美化。

想要按行讀取:

  		PDFTextStripper stripper = new PDFTextStripper();
            stripper .setSortByPosition(sort); //sort設置爲true 則按照行進行讀取,默認是false

可以按照指定的模板,對pdf進行修改添加刪除等操作,總之操作很騷,很強大。

1 pdfbox 需要帶入依賴

   <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.15</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/fontbox -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>fontbox</artifactId>
            <version>2.0.15</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/jempbox -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>jempbox</artifactId>
            <version>1.8.16</version>
        </dependency>

2 代碼

/**
 * 功能 PDF讀寫類
 * @CreateTime 2011-4-14 下午02:44:11
 */
public class PDFUtil {

    //  public static final String CHARACTOR_FONT_CH_FILE = "SIMFANG.TTF";  //仿宋常規
    public static final String CHARACTOR_FONT_CH_FILE = "SIMHEI.TTF";  //黑體常規

    public static final Rectangle PAGE_SIZE = PageSize.A4;
    public static final float MARGIN_LEFT = 50;
    public static final float MARGIN_RIGHT = 50;
    public static final float MARGIN_TOP = 50;
    public static final float MARGIN_BOTTOM = 50;
    public static final float SPACING = 20;


    private Document document = null;

    /**
     * 功能:創建導出數據的目標文檔
     * @param fileName 存儲文件的臨時路徑
     * @return
     */
    public void createDocument(String fileName) {
        File file = new File(fileName);
        FileOutputStream out = null;
        document = new Document(PAGE_SIZE, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, MARGIN_BOTTOM);
        try {
            out = new FileOutputStream(file);
//          PdfWriter writer =
            PdfWriter.getInstance(document, out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        // 打開文檔準備寫入內容
        document.open();
    }

    /**
     * 將章節寫入到指定的PDF文檔中
     * @param chapter
     * @return
     */
    public void writeChapterToDoc(Chapter chapter) {
        try {
            if(document != null) {
                if(!document.isOpen()) document.open();
                document.add(chapter);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 功能  創建PDF文檔中的章節
     * @param title 章節標題
     * @param chapterNum 章節序列號
     * @param alignment 0表示align=left,1表示align=center
     * @param numberDepth 章節是否帶序號 設值=1 表示帶序號 1.章節一;1.1小節一...,設值=0表示不帶序號
     * @param font 字體格式
     * @return Chapter章節
     */
    public static Chapter createChapter(String title, int chapterNum, int alignment, int numberDepth, Font font) {
        Paragraph chapterTitle = new Paragraph(title, font);
        chapterTitle.setAlignment(alignment);
        Chapter chapter = new Chapter(chapterTitle, chapterNum);
        chapter.setNumberDepth(numberDepth);
        return chapter;
    }

    /**
     * 功能:創建某指定章節下的小節
     * @param chapter 指定章節
     * @param title 小節標題
     * @param font 字體格式
     * @param numberDepth 小節是否帶序號 設值=1 表示帶序號 1.章節一;1.1小節一...,設值=0表示不帶序號
     * @return section在指定章節後追加小節
     */
    public static Section createSection(Chapter chapter, String title, Font font, int numberDepth) {
        Section section = null;
        if(chapter != null) {
            Paragraph sectionTitle = new Paragraph(title, font);
            sectionTitle.setSpacingBefore(SPACING);
            section = chapter.addSection(sectionTitle);
            section.setNumberDepth(numberDepth);
        }
        return section;
    }

    /**
     * 功能:向PDF文檔中添加的內容
     * @param text 內容
     * @param font 內容對應的字體
     * @return phrase 指定字體格式的內容
     */
    public static Phrase createPhrase(String text,Font font) {
        Phrase phrase = new Paragraph(text,font);
        return phrase;
    }

    /**
     * 功能:創建列表
     * @param numbered  設置爲 true 表明想創建一個進行編號的列表
     * @param lettered 設置爲true表示列表採用字母進行編號,爲false則用數字進行編號
     * @param symbolIndent
     * @return list
     */
    public static List createList(boolean numbered, boolean lettered, float symbolIndent) {
        List list = new List(numbered, lettered, symbolIndent);
        return list;
    }

    /**
     * 功能:創建列表中的項
     * @param content 列表項中的內容
     * @param font 字體格式
     * @return listItem
     */
    public static ListItem createListItem(String content, Font font) {
        ListItem listItem = new ListItem(content, font);
        return listItem;
    }

    /**
     * 功能:創造字體格式
     * @param fontname
     * @param size 字體大小
     * @param style 字體風格
     * @param color 字體顏色
     * @return Font
     */
    public static Font createFont(String fontname, float size, int style, BaseColor color) {
        Font font =  FontFactory.getFont(fontname, size, style, color);
        return font;
    }

    /**
     * 功能: 返回支持中文的字體---仿宋
     * @param size 字體大小
     * @param style 字體風格
     * @param color 字體 顏色
     * @return  字體格式
     */
    public static Font createCHineseFont(float size, int style, BaseColor color) {
        BaseFont bfChinese = null;
        try {
            bfChinese = BaseFont.createFont(CHARACTOR_FONT_CH_FILE,BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new Font(bfChinese, size, style, color);
    }

    /**
     * 最後關閉PDF文檔
     */
    public void closeDocument() {
        if(document != null) {
            document.close();
        }
    }


    /**
     * 讀PDF文件,使用了pdfbox開源項目
     * @param fileName
     */
    public static  void readPDF(String fileName) {
        File file = new File(fileName);
        FileInputStream in = null;
        try {
            in = new FileInputStream(fileName);
            // 新建一個PDF解析器對象
            PDFParser parser = new PDFParser(new RandomAccessFile(file,"rw"));
            // 對PDF文件進行解析
            parser.parse();
            // 獲取解析後得到的PDF文檔對象
            PDDocument pdfdocument = parser.getPDDocument();
            // 新建一個PDF文本剝離器
            PDFTextStripper stripper = new PDFTextStripper();
              stripper .setSortByPosition(sort); //sort設置爲true 則按照行進行讀取,默認是false
            // 從PDF文檔對象中剝離文本
            String result = stripper.getText(pdfdocument);
            FileWriter fileWriter = new FileWriter(new File("pdf.txt"));
            fileWriter.write(result);
            fileWriter.flush();
            fileWriter.close();
            System.out.println("PDF文件的文本內容如下:");
            System.out.println(result);

        } catch (Exception e) {
            System.out.println("讀取PDF文件" + file.getAbsolutePath() + "生失敗!" + e);
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
            }
        }
    }


    /**
     * 測試pdf文件的創建
     * @param args
     */
    public static void main(String[] args) {

        String fileName = "C:\Users\tizzy\Desktop\測試.pdf";  //這裏先手動把絕對路徑的文件夾給補上。
        PDFUtil pdfUtil = new PDFUtil();
        pdfUtil.writeChapterToDoc(chapter);
        pdfUtil.closeDocument();
    }
}

解析後的內容格式

合 計
備
注
xxxxxxxxxxx普通發票
價稅合計(大寫) (小寫)
貨物或應稅勞務、服務名稱 規格型號 單位 數 量 單 價 金 額 稅率 稅 額
購
買
方
銷
售
方
收 款 人: 復 核: 開 票 人: 銷 售 方:(章)
密
碼
區
機器編號:
名    稱:
納稅人識別號:
地 址、
開戶行及賬號:
名    稱:
納稅人識別號:
地 址、
開戶行及賬號:
發票代碼:
發票號碼:
開票日期:
校 驗 碼:
電 話:
電 話:
¥1.00 ¥0.06
*xxxxxxxxxxx 1 1 1.00 6% 0.06
499111xxx80
壹圓零陸分
收款人 複覈人 開票人
0 3 < < 7 9 2 9 > 5 8 4 3 > 2 3 1xxxx / 3 5 0 > 3 5 8 1
> 7 6 3 8 > 1 - x + 1x 5 4 6 * 1 + 7xxx 8 < / 0 3 + 9
7 > < < 7 9 2 9 > 5 xxxx 4 3 > 2 3 1 2 > * + * - + 1 / 9 9
2 2 xx + 4 - < 4 2 9 0 1 - + 0 - 1 9xxxx5 / + 0 0 < 8 > 7
test
xxxx
9150000xxxxA
重慶市xxxxxxxx號、7號xxxxx-xxxxx
招商銀行1xxxxxxxxxx0
15xxxxxx1666
544xxxxx880
2019年04月10日
151xxx1 89xx13 56xx5 85xx80
¥1.06

第二種 使用國產的框架 Spire.PDF

#####包含兩種版本 1 免費版 https://www.e-iceblue.cn/Downloads/Free-Spire-PDF-JAVA.html

友情提示: 免費版有 10 頁的頁數輸出限制,在輸出結果文檔時只能輸出前10頁。將 PDF 文檔轉換爲圖片、Word、HTML、XPS等格式時,僅支持轉換前 10 頁。如超出限制,可升級到商業版,我們僅對免費版進行不定期維護。

2 商業版本 https://www.e-iceblue.cn/Introduce/Spire-PDF-JAVA.html

api http://e-iceblue.cn/licensing/install-spirepdf-for-java-from-maven-repository.html

特點:商業版本收費,免費版本有限制,可供開發人員調試,解析格式友好,解析結果是按照行顯示,對pdf 圖形 ,水印 ,文本, 條形碼等添加增刪改操作,總之個人感覺比pdfbox順手,但就是收費啊,誰讓咱公司沒錢呢。

主要功能

只需 Free Spire.PDF for Java,無需 Adobe Acrobat Free Spire.PDF for Java 是一款完全獨立的 PDF 類庫。它的運行環境無需安裝 Adobe Acrobat 或其他任何第三方組件。 多樣化的PDF文檔操作功能 Free Spire.PDF for Java 支持畫文本、圖片、表格、條形碼、形狀到 PDF,提取文本和圖片,創建、填充和刪除 PDF 表單,添加文本/圖片水印到 PDF,添加、更新和刪除 PDF 書籤,操作超鏈接、附件和註釋,以及添加圖片/文本印章到 PDF 等。 文檔信息設置 Free Spire.PDF for Java 支持設置 PDF 文檔信息,例如文檔屬性設置,偏好設置(頁面方向,頁面大小,縮放比例等)。 高質量的文檔轉換功能 Free Spire.PDF for Java 支持將 PDF 文檔高質量地轉換爲 Word、HTML、XPS、圖片、SVG 和 PDF/A 格式,以及將 XPS 文檔高質量地轉換爲 PDF 格式。 文檔安全性設置 Free Spire.PDF for Java 支持給 PDF 文檔添加和驗證數字簽名,加密和解密 PDF 文檔,修改 PDF 文檔的安全權限,以及檢測簽名後的 PDF 文檔是否被修改。 易於集成 開發人員可以輕易地將 Free Spire.PDF for Java 集成到 Java(J2SE和J2EE)應用程序中。

api 更多功能如下圖 在這裏插入圖片描述

在這裏插入圖片描述 1 倉庫地址 和 依賴

<repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
</repositories>
<dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf.free</artifactId>
        <version>2.2.2</version>
    </dependency>
<

2 代碼

//創建PdfDocument實例
PdfDocument doc = new PdfDocument();
//加載PDF文件
doc.loadFromFile("C:\\Users\\tizzy\\Desktop\\測試.pdf");

//創建StringBuilder實例
StringBuilder sb = new StringBuilder();

PdfPageBase page;
//遍歷PDF頁面,獲取每個頁面的文本並添加到StringBuilder對象
for(int i= 0;i<doc.getPages().getCount();i++){
    page = doc.getPages().get(i);
    sb.append(page.extractText(true));
}
FileWriter writer;
try {
    //將StringBuilder對象中的文本寫入到文本文件
    writer = new FileWriter("ExtractText.txt");
    writer.write(sb.toString());
    writer.flush();
} catch (IOException e) {
    e.printStackTrace();
}

doc.close();

解析後格式內容如圖

在這裏插入圖片描述

第三種 使用iTika 進行解析pdf

api : https://tika.apache.org/

對中文支持不是很友好,解析的格式和pdfbox類似

1依賴


        <!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-core</artifactId>
            <version>1.20</version>
        </dependency>

2 代碼

public static String getPdfFileText(String fileName) throws IOException {
       PdfReader reader = new PdfReader(fileName);
       PdfReaderContentParser parser = new PdfReaderContentParser(reader);
       StringBuffer buff = new StringBuffer();
       TextExtractionStrategy strategy;
       for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            strategy = parser.processContent(i,
                      new SimpleTextExtractionStrategy());
            buff.append(strategy.getResultantText());
           }
       return buff.toString();
      }

解析後內容格式類似pdfbox

總結

幾種方式各有利弊,開源也罷,閉源也罷,其中利弊自己權衡。

關注我

公衆號二維碼

如果你喜歡這篇文章,喜歡,在看,轉發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章