系列文章:
Java 操作 Office:POI 之 word 生成
Java 操作 Office:POI 之 word 图片处理
Java 操作 Office:POI word 之网络图片处理
Java 操作 Office:POI word 之表格格式
一 POI简介
Apache POI - the Java API for Microsoft Documents。根据官网描述,poi是微软文档系列的Java API。这里的微软文档(Microsoft Documents),就是指word、excel(xls 和 xlsx)、PowerPoint 等。poi官网地址:https://poi.apache.org/。目前最新版本为 22年1月14日发布的POI5.2.0。发布记录可参见:RELEASE-NOTES;change log:changes;下载列表:https://archive.apache.org/dist/poi/release/bin/
二 POI组成
2.1 4.1.0与5.2.0版本组成
我们下载了4.1.0 和 5.2.0 两个版本的bin包,并解压后进行对比:
auxiliary,lib,ooxml-lib几个目录相同,内部依赖暂时不做对比。下面的jar包是我们开发时需要引入的依赖。poi-${version}.jar, poi-examples-${version}.jar, poi-excelant-${version}.jar, poi-ooxml-${version}.jar, poi-scratchpad-${version}.jar,这几个是相同的。不同的地方是,4.1.0中的 poi-ooxml-schemas-${version}.jar,在5.2.0中变成了poi-ooxml-full-${version}.jar和poi-ooxml-lite-${version}.jar。
2.2 各jar包作用
在官网的components中有描述:Apache POI - Component Overview,这更详细的解释大家可以直接看原文内容:https://poi.apache.org/components/index.html。
下图是操作的文档类型与jar包之间的关系,通过这张表,可以明确当我们仅需要操作word或excel,以及2003或2007版本时,分别需要引入哪几个jar包(或maven依赖):
poi包内各jar包之间的依赖关系:
举个栗子:
只要操作excel,且是xls格式时,只需导入poi-version-yyyymmdd.jar。当我们还要使用xlsx格式、还要导入poi-ooxml-version-yyyymmdd.jar。至于poi-ooxml-schemas-version-yyyymmdd.jar这个jar基本不太会用到的。当我们需要操作word、ppt、viso、outlook等时需要用到poi-scratchpad-version-yyyymmdd.jar。
三 读取word内容
在本文开始挂的系列文章链接中,已经包含了word文档创建、生成表格等相关操作,接下来我们要尝试读取word文档内容,最好包含格式,这样可以配合前端实现word在线编辑的效果,方便在web系统中集成;也可以考虑通过这种方式配合自然语言处理的相关模型/服务,实现word文档关键内容提取。
如大家所熟知,word目前也有.doc 和 .docx两种格式,对这两种格式的读取方式也稍有不同。接下来我们通过代码来详细阐述。
3.1 poi版本和依赖引入
我们使用的是4.1.0版本的poi,引入的依赖如下:
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>test</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>project</artifactId>
<properties>
<java.version>1.8</java.version>
<poi.version>4.1.0</poi.version>
</properties>
<dependencies>
<!-- office 相关依赖jar包 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
</dependencies>
</project>
代码语言:javascript复制
3.2 docx文件内容读取
通过XWPFWordExtractor读取文档内容:
代码语言:javascript复制import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
public class ReadWordContent {
public static void main(String[] args) throws Exception {
String wordPath = "你的word文档地址.docx";
ReadWordContent readWordContent = new ReadWordContent();
readWordContent.readByExtractor(wordPath);
}
/**
* 通过XWPFWordExtractor访问XWPFDocument的内容
* @throws Exception
*/
public void readByExtractor(String path) throws Exception {
InputStream is = new FileInputStream(path);
XWPFDocument doc = new XWPFDocument(is);
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
String text = extractor.getText();
System.out.println(text);
/**
* 打印文档信息
*/
POIXMLProperties.CoreProperties coreProps = extractor.getCoreProperties();
this.printCoreProperties(coreProps);
this.close(is);
}
/**
* 输出CoreProperties信息
* @param coreProps
*/
private void printCoreProperties(POIXMLProperties.CoreProperties coreProps) {
String category = coreProps.getCategory(); //分类
String creator = coreProps.getCreator(); //创建者,Microsoft Office User
Date createdDate = coreProps.getCreated(); //创建时间
String title = coreProps.getTitle(); //标题
String description = coreProps.getDescription(); //描述,默认为null
System.out.println(category);
System.out.println(creator);
System.out.println(createdDate);
System.out.println(title);
System.out.println(description);
}
/**
* 关闭输入流
* @param is
*/
private void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
代码语言:javascript复制
3.3 doc文档内容及格式读取
代码语言:javascript复制import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.StyleDescription;
import org.apache.poi.hwpf.model.StyleSheet;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import java.io.*;
/**
* 注:HWPFDocument对应 word的.doc,不支持.docx
*/
public class ReadWordWithFormat {
public static void main(String[] args) throws Exception {
String filePath = "你的word文档地址.doc";
printWord(filePath);
}
public static void printWord(String filePath) throws IOException {
InputStream is = new FileInputStream(filePath);
HWPFDocument doc = new HWPFDocument(is);
Range r = doc.getRange();// 文档范围
// System.out.println("段落数:" r.numParagraphs());
for (int i = 0; i < r.numParagraphs(); i ) {
Paragraph p = r.getParagraph(i);// 获取段落
int numStyles = doc.getStyleSheet().numStyles();
int styleIndex = p.getStyleIndex();
StyleSheet style_sheet = doc.getStyleSheet();
StyleDescription style = style_sheet.getStyleDescription(styleIndex);
String styleName = style.getName();
// 打印各段落的格式
System.out.println(i "," styleIndex "," styleName);
// String styleLoving = "标题";
// if (!StringUtils.isEmpty(styleName) && styleName.startsWith(styleLoving)){
// String text = p.text();// 段落文本
// System.out.println(text);
// }
}
doc.close();
}
}
代码语言:javascript复制
在printWord()方法中,我们打印了文档的每个段落以及该段落的格式,以本地测试时使用的文档为例,输出如下:
代码语言:javascript复制0,0,正文
1,0,正文
2,1,标题 1
3,2,标题 2
4,0,正文
5,2,标题 2
6,0,正文
7,2,标题 2
8,0,正文
9,0,正文
10,0,正文
11,2,标题 2
12,0,正文
13,1,标题 1
14,2,标题 2
15,0,正文
16,0,正文
17,2,标题 2
18,0,正文
19,1,标题 1