Java開發(fā)中讀取與解析Word文檔的實(shí)踐教學(xué)
日常開發(fā)中,難免會(huì)遇到需要解析 Word 文檔的場(chǎng)景。比如搭建文檔管理系統(tǒng)時(shí)需要提取上傳文件的內(nèi)容,或者做數(shù)據(jù)遷移時(shí)要批量處理存量文檔。這類需求如果處理不好,往往會(huì)帶來(lái)不少麻煩。本文將整理幾種在 Java 環(huán)境下讀取 Word 文檔內(nèi)容的實(shí)用方法,涵蓋全文提取、段落解析、表格讀取和圖片導(dǎo)出,希望能給遇到類似需求的開發(fā)者一些參考。
一、依賴引入
開始寫代碼之前,先把必要的依賴配置好。以 Maven 項(xiàng)目為例,在 pom.xml 中添加如下內(nèi)容:
<repositories>
<repository>
<id>com.e-iceblue</id>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>14.5.3</version>
</dependency>
</dependencies>依賴就緒后,就可以正式開始編寫讀取邏輯了。
二、提取文檔的全部文本
如果需求比較簡(jiǎn)單直接,比如只想把文檔里的文字提取出來(lái)做全文檢索或者關(guān)鍵詞分析,那么一次性讀取所有文本是最高效的做法。
import com.spire.doc.Document;
public class ReadAllText {
public static void main(String[] args) {
Document doc = new Document();
doc.loadFromFile("sample.docx");
// 獲取文檔的完整文本內(nèi)容
String allText = doc.getText();
System.out.println(allText);
doc.close();
}
}
getText() 方法會(huì)把整篇文檔的段落文字拼接成一個(gè)字符串,表格中的文字也會(huì)一并包含在內(nèi)。這種方式勝在簡(jiǎn)潔,幾行代碼就能搞定。但缺點(diǎn)也很明顯——所有內(nèi)容平鋪在一起,標(biāo)題、正文、表格內(nèi)容混在一塊,丟失了原有的文檔結(jié)構(gòu)。
三、按段落逐條讀取
當(dāng)我們需要了解文檔的結(jié)構(gòu)層次,或者只關(guān)心特定樣式的內(nèi)容時(shí),逐段落地讀取就顯得很有必要了。比如只提取所有的一級(jí)標(biāo)題,或者跳過(guò)頁(yè)眉頁(yè)腳只處理正文。
import com.spire.doc.Document;
import com.spire.doc.documents.Paragraph;
public class ReadParagraphs {
public static void main(String[] args) {
Document doc = new Document();
doc.loadFromFile("sample.docx");
// 遍歷文檔中的節(jié)
for (int i = 0; i < doc.getSections().getCount(); i++) {
// 遍歷每個(gè)節(jié)中的段落
for (int j = 0; j < doc.getSections().get(i).getParagraphs().getCount(); j++) {
Paragraph paragraph = doc.getSections().get(i).getParagraphs().get(j);
String text = paragraph.getText();
String styleName = paragraph.getStyleName();
System.out.println("樣式: " + styleName);
System.out.println("內(nèi)容: " + text);
System.out.println("---");
}
}
doc.close();
}
}
這里的關(guān)鍵是 getStyleName() 方法,它返回段落在 Word 中應(yīng)用樣式后的名稱,比如 "Heading1"、"Heading2"、"Normal" 等等。拿到樣式名之后,我們就可以方便地過(guò)濾出想要的段落類型。除此之外,Paragraph 對(duì)象還能提供對(duì)齊方式、縮進(jìn)值、行距等格式信息,有需要的話可以進(jìn)一步挖掘。
四、讀取表格中的結(jié)構(gòu)化數(shù)據(jù)
表格在 Word 里往往扮演著承載結(jié)構(gòu)化數(shù)據(jù)的角色,比如項(xiàng)目排期表、人員信息表、價(jià)格清單等等。把這些數(shù)據(jù)準(zhǔn)確讀取出來(lái),是很多業(yè)務(wù)場(chǎng)景下的剛性需求。
import com.spire.doc.Document;
import com.spire.doc.Section;
import com.spire.doc.Table;
import com.spire.doc.TableRow;
import com.spire.doc.TableCell;
public class ReadTable {
public static void main(String[] args) {
Document doc = new Document();
doc.loadFromFile("sample.docx");
// 遍歷所有節(jié)
for (int i = 0; i < doc.getSections().getCount(); i++) {
Section section = doc.getSections().get(i);
// 遍歷當(dāng)前節(jié)中的表格
for (int j = 0; j < section.getTables().getCount(); j++) {
Table table = section.getTables().get(j);
System.out.println("表格 " + (j + 1) + ":");
// 按行讀取
for (int k = 0; k < table.getRows().getCount(); k++) {
TableRow row = table.getRows().get(k);
// 按單元格讀取
for (int l = 0; l < row.getCells().getCount(); l++) {
TableCell cell = row.getCells().get(l);
System.out.print(cell.getText() + "\t");
}
System.out.println();
}
System.out.println("============");
}
}
doc.close();
}
}
代碼邏輯比較清晰,按節(jié)、表格、行、單元格的層級(jí)逐層遍歷。讀出來(lái)的數(shù)據(jù)可以根據(jù)需要組裝成二維數(shù)組或 List,方便后續(xù)寫入數(shù)據(jù)庫(kù)或?qū)С鰹?Excel。有一點(diǎn)需要留意:如果文檔中的表格存在合并單元格的情況,按行列索引直接讀取時(shí)可能會(huì)遇到空值或者數(shù)據(jù)位置偏移,實(shí)際項(xiàng)目里最好加上對(duì)合并單元格的判斷處理。
五、導(dǎo)出文檔中的圖片
文字和表格之外,圖片也是 Word 文檔中常見的內(nèi)容類型。有時(shí)候我們需要把文檔里的圖片提取出來(lái)單獨(dú)存儲(chǔ),比如遷移到圖床或者存入資源管理系統(tǒng)。
import com.spire.doc.Document;
import com.spire.doc.fields.DocPicture;
import com.spire.doc.interfaces.IDocumentObject;
public class ExtractImages {
public static void main(String[] args) throws Exception {
Document doc = new Document();
doc.loadFromFile("sample.docx");
int imageIndex = 0;
// 遍歷文檔中的子對(duì)象
for (int i = 0; i < doc.getSections().getCount(); i++) {
for (int j = 0; j < doc.getSections().get(i).getBody().getChildObjects().getCount(); j++) {
IDocumentObject obj = doc.getSections().get(i).getBody().getChildObjects().get(j);
// 判斷是否為圖片對(duì)象
if (obj instanceof DocPicture) {
DocPicture picture = (DocPicture) obj;
// 保存為 PNG 文件
picture.getImage().save("output/image_" + imageIndex + ".png", null);
imageIndex++;
}
}
}
System.out.println("共提取 " + imageIndex + " 張圖片");
doc.close();
}
}
圖片會(huì)按編號(hào)依次保存到輸出目錄。如果文檔里圖片比較多,建議文件命名時(shí)加入更具體的標(biāo)識(shí),避免同名覆蓋。另外除了正文中的圖片,頁(yè)眉頁(yè)腳和文本框里也可能藏著圖片對(duì)象,按需決定要不要一并處理。
六、幾點(diǎn)實(shí)用建議
在實(shí)際項(xiàng)目中使用時(shí),有幾個(gè)細(xì)節(jié)值得留意。第一是格式兼容性,.doc 和 .docx 兩種格式都可以用同一套 API 加載,不需要分別寫兩套邏輯,這在實(shí)際開發(fā)中能省不少事。第二是資源釋放,文檔讀取完畢后記得調(diào)用 close() 方法,否則文件可能會(huì)被進(jìn)程持續(xù)占用,導(dǎo)致后續(xù)的寫入或刪除操作失敗。第三是對(duì)大文件的處理,如果文檔體量較大,解析會(huì)消耗更多時(shí)間和內(nèi)存,在并發(fā)場(chǎng)景下建議提前做好壓測(cè),必要時(shí)對(duì)大文件做異步處理或設(shè)置超時(shí)機(jī)制。
七、最后
本文梳理了 Java 環(huán)境下讀取 Word 文檔內(nèi)容的幾種常見方式,從最直接的全文文本提取,到保留結(jié)構(gòu)的段落遍歷與樣式識(shí)別,再到表格數(shù)據(jù)解析和圖片資源導(dǎo)出,基本覆蓋了日常開發(fā)中會(huì)遇到的典型場(chǎng)景。這些方法可以靈活搭配使用,比如在文檔入庫(kù)時(shí)同時(shí)提取純文本做索引、解析表格做結(jié)構(gòu)化存儲(chǔ)、導(dǎo)出圖片做獨(dú)立資源管理。掌握了這些基礎(chǔ)操作之后,再面對(duì)更復(fù)雜的文檔處理需求,心里也會(huì)有底,實(shí)現(xiàn)起來(lái)會(huì)更加從容。
以上就是Java開發(fā)中讀取與解析Word文檔的實(shí)踐教學(xué)的詳細(xì)內(nèi)容,更多關(guān)于Java讀取與解析Word的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java多線程實(shí)現(xiàn)聊天客戶端和服務(wù)器
這篇文章主要為大家詳細(xì)介紹了Java多線程聊天客戶端和服務(wù)器實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
基于request獲取訪問(wèn)者真實(shí)IP代碼示例
這篇文章主要介紹了基于request獲取訪問(wèn)者真實(shí)IP代碼示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
MyBatis-Flex+ShardingSphere-JDBC多數(shù)據(jù)源分庫(kù)分表實(shí)現(xiàn)
本文介紹了使用MyBatis-Flex和ShardingSphere-JDBC實(shí)現(xiàn)多數(shù)據(jù)源分庫(kù)分表的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10

