Java PDF处理:用 PDFBox 三步跑通文本提取、合并拆分与页面渲染
【免费下载链接】pdfboxMirror of Apache PDFBox项目地址: https://gitcode.com/gh_mirrors/pd/pdfbox
PDFBox 是 Apache 基金会出品的 Java PDF 处理库,也是目前 Java 生态里最成熟的开源 PDF 方案。你想从 PDF 里抓文字、把几个文档拼成一个、或者把页面导出成图片,它都能用几行代码解决。这篇文章面向第一次接触它的开发者,带你从克隆代码到跑通第一个 PDF。
📍 项目定位速览:它能帮你做哪几件事
PDFBox 的核心能力可以概括成四件事:
- 创建新 PDF 并写入文本、图片、表单
- 从 PDF 中提取文本、元数据、嵌入文件
- 合并、拆分、叠加页面
- 把 PDF 页面渲染成 PNG/JPEG 图片
运行环境要求很简单,满足这两条就能开工:
- JDK 11 或更高版本
- Maven 3.x(依赖由 Maven 统一管理,不需要手动配置)
🏃 跑起来:两条命令出第一个 PDF
克隆仓库到本地:
git clone https://gitcode.com/gh_mirrors/pd/pdfbox进入目录后跳过测试构建,速度最快:
cd pdfbox mvn clean install -DskipTests构建完成后,app模块会生成一个pdfbox-app-*.jar。用它跑一次文本提取验证环境:
java -jar app/target/pdfbox-app-*.jar ExtractText your.pdf out.txt能生成out.txt,说明整条链路已经通了。
📝 核心能力实战
手写一个 PDF:创建、写文本、保存
最小创建流程就是"建文档→加页→开内容流→写文本"四步:
try (PDDocument doc = new PDDocument()) { PDPage page = new PDPage(); doc.addPage(page); // 内容流负责往页面上写内容,必须用 try-with-resources 关闭 try (PDPageContentStream cs = new PDPageContentStream(doc, page)) { cs.beginText(); cs.setFont(new PDType1Font(FontName.HELVETICA_BOLD), 12); // 内置14字体无需外部文件 cs.newLineAtOffset(100, 700); cs.showText("Hello PDFBox"); cs.endText(); } doc.save("hello.pdf"); }常见坑:PDPageContentStream不关闭,文件会写不完整甚至损坏。想写中文,换成PDType0Font.load(doc, "simsun.ttc")加载 TrueType 字体即可,完整写法仓库里有examples/.../HelloWorldTTF.java。
提取文本:一行 stripper 拿到全文
文本提取是最高频的场景,PDFTextStripper默认按页遍历、按行拼接:
try (PDDocument doc = Loader.loadPDF(new File("input.pdf"))) { PDFTextStripper stripper = new PDFTextStripper(); String text = stripper.getText(doc); // 内部逐页解析内容流并重组 }常见坑:提取结果是空白或乱码。要么文档是扫描件(没有文字层,见后文解法),要么用了特殊字体编码。按区域提取可换成PDFTextStripperByArea,它先注册区域再按区域取文本。
合并与拆分:文档级操作
多份合同合并成一个文件:
PDFMergerUtility merger = new PDFMergerUtility(); merger.addSource(new File("a.pdf")); merger.addSource(new File("b.pdf")); merger.setDestinationFileName("merged.pdf"); merger.mergeDocuments(null); // 参数传 null 用默认缓存策略拆分则用PDFSplitter按页切,或PageExtractor只取指定页。注意:合并加密文档前要先解密,否则源文档的加密参数会互相冲突。
渲染成图片:PDF 转 PNG
把页面转成位图用于预览、水印或存档:
try (PDDocument doc = Loader.loadPDF(new File("source.pdf"))) { PDFRenderer renderer = new PDFRenderer(doc); // dpi 控制清晰度,144 约等于 2 倍屏 BufferedImage image = renderer.renderImageWithDPI(0, 144, ImageType.RGB); ImageIO.write(image, "png", new File("page0.png")); }上图就是renderImageWithDPI对一个真实 PDF 的渲染输出。常见坑:渲染大图时开高 DPI 直接 OOM,解法是调低 DPI,或对超大图像开启renderer.setSubsamplingAllowed(true)让大图下采样。
⚠️ 上手后你会遇到的坑
处理大 PDF 内存暴涨→PDDocument默认尽量驻留内存 → 构建时用MemoryUsageSetting.setupTempFileOnly()让流数据走磁盘临时文件,大文件建议Loader.loadPDF(file, MemoryUsageSetting.setupTempFileOnly())。
提取文本得到空字符串→ 文档是扫描图片,本身没有文字层 → 用PDFRenderer渲染成图片后再接 OCR,PDFBox 自己不做识别。
打开文件抛InvalidPasswordException→ 文档带打开密码 → 先调用doc.getEncryptionHandler().authenticate("密码"),成功后才能正常读取,密码错误时该调用不会抛异常,只返回false,需要自己判断。
🧭 往哪走:源码里最该看的三个地方
- 示例库 examples/src/main/java/org/apache/pdfbox/examples/pdmodel/:38 个可直接运行的场景样例,创建、书签、嵌字体、加水印都有可抄的最小实现。
- 渲染引擎 pdfbox/src/main/java/org/apache/pdfbox/rendering/:
PDFRenderer和PageDrawer的实现细节,想调渲染行为或排查色差时看这里。 - 命令行工具 tools/src/main/java/org/apache/pdfbox/tools/:
ExtractText、PDFMerger这些 CLI 的实现,看源码比看文档更快搞懂参数。
收尾
读完这篇文章,你已经能独立创建带文字的 PDF、提取全文、合并拆分文档,并把页面渲染成图片。下一步建议:打开examples目录,挑一个HelloWorldTTF.java用 Maven 直接跑通,然后照着它改成你自己的第一个业务文档。
【免费下载链接】pdfboxMirror of Apache PDFBox项目地址: https://gitcode.com/gh_mirrors/pd/pdfbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考