如何使用Apache PDFBox获取PDF文件中的文本字体大小
基于Apache PDFBox提取PDF已使用字体大小的实现方案
核心逻辑
PDF中的字体大小不会直接全局存储,需要在解析每个文本片段时,通过当前文本的变换矩阵计算得出实际pt单位值。Apache PDFBox提供了TextPosition类封装了所有文本相关的属性,你只需要自定义PDFTextStripper的子类,重写文本处理的回调方法即可获取到所有字号数据。
实现步骤
- 自定义继承
PDFTextStripper的工具类,内部维护集合用来存储去重后的字号值,避免重复统计相同字号 - 重写
processTextPosition(TextPosition text)方法,该方法会在解析每个文本片段时自动触发 - 直接调用
TextPosition提供的getFontSizeInPt()方法获取已换算为pt单位的字号值,PDFBox 2.0及以上版本已内置该方法,无需自行计算矩阵 - 全页解析完成后,从维护的集合中即可获取文档中所有已使用的字号
可运行示例代码
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.TextPosition; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Set; public class FontSizeExtractor extends PDFTextStripper { // 存储去重后的已使用字号,单位pt private final Set<Float> usedFontSizes = new HashSet<>(); public FontSizeExtractor() throws IOException { super(); } @Override protected void processTextPosition(TextPosition text) { float fontSizePt = text.getFontSizeInPt(); // 处理浮点精度问题,保留1位小数,可根据需求调整精度 fontSizePt = Math.round(fontSizePt * 10) / 10f; usedFontSizes.add(fontSizePt); // 保留父类逻辑,不影响原有文本提取功能 super.processTextPosition(text); } public Set<Float> getUsedFontSizes() { return usedFontSizes; } public static void main(String[] args) throws IOException { // 替换为你的PDF文件路径 try (PDDocument document = PDDocument.load(new File("test.pdf"))) { FontSizeExtractor extractor = new FontSizeExtractor(); // 设置解析所有页面 extractor.setStartPage(1); extractor.setEndPage(document.getNumberOfPages()); // 触发文本解析流程,无需使用返回的文本内容 extractor.getText(document); // 输出排序后的所有字号 System.out.println("文档中已使用的字体大小(单位pt):"); extractor.getUsedFontSizes().stream().sorted().forEach(size -> System.out.println(size + "pt")); } } }
注意事项
- 若使用PDFBox 1.x版本,无内置
getFontSizeInPt()方法,可通过text.getTextMatrix().getScalingFactorY()自行计算,结果即为pt单位字号 - 可根据业务需求调整精度处理逻辑,避免因为PDF渲染的浮点误差导致同一个字号被识别为多个接近的数值
- 如果需要关联字号和对应文本内容,可在
processTextPosition方法中同时获取text.getUnicode()属性,存入自定义实体类集合即可
内容的提问来源于stack exchange,提问作者Cheeky Crex
相关产品推荐
相关产品推荐

