发布于2026-07-11 阅读(0)
扫一扫,手机访问
在 Ja va 项目中处理 PDF 文档,最常遇到也最头疼的需求,恐怕就是解析了——把里面的文字、表格、图片和元数据提取出来,供后续搜索、分析或迁移使用。生成或编辑 PDF 还算可控,但解析考验的是库对文档结构的还原能力,以及对各种异常布局的容错性。

最近我在做一个文档自动化处理系统,把 PDF 解析拆成了几个独立的步骤:加载验证、文本抽取、表格识别、图片导出、元数据读取。每个步骤单独封装,这样既方便复用,遇到复杂文档时也能快速定位问题。下面就是我的实践记录。
第一步自然是要把解析库请进项目。这里用的是 Spire.PDF for Ja va,它提供了一套专门用于解析的 API(PdfTextExtractor、PdfTableExtractor、PdfImageHelper 等)。如果用 Ma ven,在 pom.xml 里加上配置就行:
com.e-iceblue e-iceblue https://repo.e-iceblue.cn/repository/ma ven-public/ e-iceblue spire.pdf 12.7.0
不是 Ma ven 用户的话,直接去官网下载 JAR 包,加到类路径里也一样。
开始解析之前,先加载并验证文档是个好习惯。这一步能提前发现损坏或不支持的 PDF,避免后续解析时引发连锁异常。
import com.spire.pdf.PdfDocument;
public class LoadPDF {
public static void main(String[] args) {
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("sample.pdf");
int pageCount = pdf.getPages().getCount();
System.out.println("总页数: " + pageCount);
}
}
这段代码加载一个 PDF,然后获取总页数。如果顺利执行,说明文件格式合规、文档结构可解析、页面树也能正常访问。生产环境里,建议把这一步做成前置校验——失败了就直接拒绝处理,别浪费后续资源。
文本提取是最常见的解析操作。但与简单读取字符串不同,PDF 里的文本是由字形(glyph)位置拼合出来的,不是天然段落。所以提取时最好用可配置的提取器,比如 PdfTextExtractor 配合 PdfTextExtractOptions,能拿到更干净的输出。
import com.spire.pdf.PdfDocument;
import com.spire.pdf.texts.PdfTextExtractOptions;
import com.spire.pdf.texts.PdfTextExtractor;
public class ExtractPdfText {
public static void main(String[] args) {
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("sample.pdf");
StringBuilder extractedText = new StringBuilder();
PdfTextExtractOptions options = new PdfTextExtractOptions();
// 开启简单提取模式,输出的文本更连续、易读
options.setSimpleExtraction(true);
for (int i = 0; i < pdf.getPages().getCount(); i++) {
PdfTextExtractor extractor = new PdfTextExtractor(pdf.getPages().get(i));
String pageText = extractor.extract(options);
extractedText.append(pageText).append("n");
}
System.out.println(extractedText.toString());
}
}
关键点:
PdfTextExtractor 按页处理,方便定位问题页面,也利于大文档的内存控制;PdfTextExtractOptions 的 setSimpleExtraction(true) 能简化布局重建,让文本更连贯;表格解析比纯文本复杂,得从视觉对齐中推断出行列结构。这个功能我经常拿来处理财务报表、对账单这类文档。
import com.spire.pdf.PdfDocument;
import com.spire.pdf.utilities.PdfTable;
import com.spire.pdf.utilities.PdfTableExtractor;
public class ExtractPdfTable {
public static void main(String[] args) {
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("sample1.pdf");
PdfTableExtractor extractor = new PdfTableExtractor(pdf);
PdfTable[] tables = extractor.extractTable(0); // 解析第一页
if (tables != null) {
for (PdfTable table : tables) {
int rowCount = table.getRowCount();
int colCount = table.getColumnCount();
System.out.println("行数: " + rowCount + ", 列数: " + colCount);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < colCount; j++) {
sb.append(table.getText(i, j));
if (j < colCount - 1) sb.append("t");
}
if (i < rowCount - 1) sb.append("n");
}
System.out.println(sb.toString());
}
}
}
}
PdfTableExtractor 会分析页面上的文本对齐方式,自动识别表格区域。解析结果是一个 PdfTable 对象,通过行列索引就能取到每个单元格的内容。
注意:
提取图片常用于存档或复核文档中的图像资源。与文本不同,图片是嵌入页面资源中的独立对象,不受布局影响,提取起来反而更直接。
import com.spire.pdf.PdfDocument;
import com.spire.pdf.utilities.PdfImageHelper;
import com.spire.pdf.utilities.PdfImageInfo;
import ja vax.imageio.ImageIO;
import ja va.awt.image.BufferedImage;
import ja va.io.File;
public class ExtractPdfImages {
public static void main(String[] args) throws Exception {
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("sample.pdf");
PdfImageHelper helper = new PdfImageHelper();
for (int i = 0; i < pdf.getPages().getCount(); i++) {
PdfImageInfo[] infos = helper.getImagesInfo(pdf.getPages().get(i));
if (infos != null) {
for (int j = 0; j < infos.length; j++) {
BufferedImage img = infos[j].getImage();
File out = new File("images/page_" + i + "_img_" + j + ".png");
ImageIO.write(img, "PNG", out);
}
}
}
}
}
PdfImageHelper.getImagesInfo() 返回页面所有图片的信息,每个 PdfImageInfo 都包含图片数据(BufferedImage),直接保存为 PNG 或 JPEG 就行。
实用提醒:
元数据(标题、作者、主题、创建/修改日期等)是文档的“身份证”,解析它不用遍历页面,开销极小,很适合作为预处理步骤。
import com.spire.pdf.PdfDocument;
public class ParsePdfMetadata {
public static void main(String[] args) {
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("sample.pdf");
var info = pdf.getDocumentInformation();
System.out.println("标题: " + info.getTitle());
System.out.println("作者: " + info.getAuthor());
System.out.println("主题: " + info.getSubject());
System.out.println("关键词: " + info.getKeywords());
System.out.println("创建者: " + info.getCreator());
System.out.println("生成器: " + info.getProducer());
System.out.println("创建日期: " + info.getCreationDate());
System.out.println("修改日期: " + info.getModificationDate());
}
}
元数据有可能为空,使用时最好先判空。另外要清楚,这些是文档的静态属性,不会随内容变化自动更新——除非重新保存。
实际项目中,我通常会把上述解析能力组合成一条管道:先读元数据做路由,再按页提取文本、表格和图片,各自落库。但有几个地方需要留心:
PdfTextExtractOptions 或更换字体映射;pdf.close() 释放文件句柄,批量处理时尤其重要。另外,如果文档体积很大,建议按需加载或用流式处理,避免内存溢出。
以上就是在 Ja va 中解析 PDF 文档的常用套路:加载验证、文本提取、表格识别、图片导出、元数据读取。每个环节独立封装,方便组合和扩展。得益于专门的 PDF 解析库,这些操作用简洁的代码就能实现,不用自己去解析底层对象。
具体用的时候,根据文档类型(文本型还是扫描型)和业务需求选择合适的解析策略,并对异常情况做好容错。希望这些代码片段能成为日常开发中的实用参考。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8