首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Apache POI 讀取 Word 文檔完整指南:.doc/.docx 雙格式、Maven 依賴與常見坑點

     編輯:Java 相關知識

POI 版本與格式對應

Maven 依賴配置

<dependencies>
    <!-- 核心,兩種格式都需要 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.3.0</version> <!-- 檢查最新版 -->
    </dependency>
    <!-- .doc 專用 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-scratchpad</artifactId>
        <version>5.3.0</version>
    </dependency>
    <!-- .docx 專用 (含傳遞依賴: ooxml-schemas, xmlbeans, curvesapi) -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.3.0</version>
    </dependency>
</dependencies>

注意:POI 5.0+ 需 JDK 8+,poi-ooxml 已整合 ooxml-schemas、xmlbeans 等傳遞依賴,無需手動添加。

統一讀取文本內容代碼

import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import java.io.*;

public class WordTextExtractor {
    /** 自動偵測 .doc/.docx 並提取純文本 */
    public static String extractText(File file) throws Exception {
        String fileName = file.getName().toLowerCase();
        try (InputStream is = new FileInputStream(file)) {
            if (fileName.endsWith(".doc")) {
                // HWPF (.doc)
                WordExtractor extractor = new WordExtractor(is);
                return extractor.getText();
            } else if (fileName.endsWith(".docx")) {
                // XWPF (.docx)
                OPCPackage pkg = OPCPackage.open(is);
                POIXMLTextExtractor extractor = new XWPFWordExtractor(pkg);
                return extractor.getText();
            } else {
                throw new IllegalArgumentException("不支援格式: " + fileName);
            }
        }
    }

    public static void main(String[] args) {
        File docFile = new File("test.doc");
        File docxFile = new File("test.docx");

        try {
            if (docFile.exists()) {
                System.out.println("=== .doc 內容 ===");
                System.out.println(extractText(docFile));
            }
            if (docxFile.exists()) {
                System.out.println("=== .docx 內容 ===");
                System.out.println(extractText(docxFile));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

進階:結構化解析(段落、表格、樣式、圖片)

.docx (XWPF) 結構化讀取

import org.apache.poi.xwpf.usermodel.*;
import java.util.List;

public class DocxStructuredParser {
    public static void parse(File file) throws Exception {
        try (XWPFDocument doc = new XWPFDocument(OPCPackage.open(file))) {
            // 1. 段落與樣式
            for (XWPFParagraph para : doc.getParagraphs()) {
                System.out.println("段落樣式: " + para.getStyleID());
                for (XWPFRun run : para.getRuns()) {
                    System.out.printf("  文字: '%s' | 粗體: %s | 字體: %s | 大小: %s%n",
                        run.getText(0), run.isBold(), run.getFontFamily(), run.getFontSize());
                }
            }

            // 2. 表格
            for (XWPFTable table : doc.getTables()) {
                System.out.println("發現表格,行數: " + table.getNumberOfRows());
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        System.out.print("[" + cell.getText() + "] ");
                    }
                    System.out.println();
                }
            }

            // 3. 圖片 (關聯關係)
            for (XWPFParagraph para : doc.getParagraphs()) {
                for (XWPFRun run : para.getRuns()) {
                    List pics = run.getEmbeddedPictures();
                    for (XWPFPictureData pic : pics) {
                        System.out.println("圖片: " + pic.getFileName() + ", 大小: " + pic.getData().length + " bytes");
                        // Files.write(Paths.get(pic.getFileName()), pic.getData());
                    }
                }
            }
        }
    }
}

.doc (HWPF) 結構化讀取(功能較弱)

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.*;

public class DocStructuredParser {
    public static void parse(File file) throws Exception {
        try (HWPFDocument doc = new HWPFDocument(new FileInputStream(file))) {
            Range range = doc.getRange();
            // 段落
            for (int i = 0; i < range.numParagraphs(); i++) {
                Paragraph para = range.getParagraph(i);
                System.out.println("段落 " + i + ": " + para.text());
            }
            // 表格 (HWPF 表格支援有限)
            TableIterator it = new TableIterator(range);
            while (it.hasNext()) {
                Table table = it.next();
                System.out.println("表格行數: " + table.numRows());
            }
        }
    }
}

常見坑點與解決方案

格式副檔名POI 組件核心類最低 POI 版本
OLE2 二進制.docHWPFWordExtractor, HWPFDocument3.5+
OOXML.docxXWPFXWPFWordExtractor, XWPFDocument3.5+
問題原因解決
.docx 表格內容出現在文本末尾XWPFWordExtractor 先輸出段落再輸出表格用 XWPFDocument 結構化遍歷,按文檔順序處理
圖片無法提取.doc 圖片提取極困難;.docx 需遍歷 Run 的 embeddedPictures接受 .doc 圖片提取限制,.docx 用上述代碼
中文亂碼字體缺失或編碼問題確保系統安裝中文字體,POI 5.0+ 內建字體處理改善
大檔案 OOM完整載入 DOM 模型.docx 用 SAX 事件驅動 (XWPFDocument 不支援),或分頁處理
密碼保護文檔加密文檔無法直接讀取用 Decryptor (POI 3.17+) 或先移除密碼
依賴衝突 (xmlbeans/ooxml-schemas)多版本 POI 混用統一 POI 版本,排除傳遞依賴衝突

替代方案比較

方案優點缺點適用場景
Apache POI功能最全、社群活躍、純 Java記憶體佔用大、API 複雜通用 Java 專案
Apache Tika統一介面支援 1000+ 格式、自動偵測底層仍用 POI、細節控制力弱內容索引、全文搜尋、多格式批次處理
Aspose.Words商業級、渲染精準、功能極強收費、License 成本高企業級報表、列印、轉 PDF 需求
LibreOffice + CLI完美渲染、支援所有格式需安裝 LibreOffice、啟動慢、非純 Java服務端轉檔服務、批次轉 PDF

總結

  • 純文本提取:用 WordExtractor / XWPFWordExtractor 最簡單。
  • 結構化解析:.docx 用 XWPFDocument 功能完整;.doc 用 HWPF 受限。
  • 大檔案/高併發:考慮 Tika 或 LibreOffice 轉檔服務分流。
  • 依賴管理:POI 5.0+ 只需 poi、poi-scratchpad、poi-ooxml 三個核心模組。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved