You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PDFBox获取PDF选中文本的字体信息?getResources返回null求助

解决PDFTextStripperByArea获取区域字体信息的问题

哦,这个坑我之前踩过!PDFTextStripperByArea的getResources()方法确实经常返回null,因为它的核心定位是提取指定区域的文本内容,并没有为区域资源查询做专门的设计。不过别担心,我们可以通过自定义子类的方式绕开这个限制,直接拿到目标文本的字体信息,下面是具体的实现思路和代码:

方案一:自定义PDFTextStripperByArea子类,记录文本位置与字体信息

我们可以重写processTextPosition方法,在处理每个文本片段时,判断它是否落在我们定义的区域内,同时记录对应的TextPosition对象——这个对象里包含了完整的字体、字号等信息。

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import org.apache.pdfbox.text.TextPosition;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RegionTextWithFontStripper extends PDFTextStripperByArea {
    // 存储每个区域对应的所有TextPosition实例
    private final Map<String, List<TextPosition>> regionTextPositions = new HashMap<>();

    public RegionTextWithFontStripper() throws IOException {
        super();
        setSortByPosition(true); // 保持文本顺序
    }

    @Override
    protected void processTextPosition(TextPosition text) {
        super.processTextPosition(text);
        // 遍历所有已定义的区域,判断当前文本是否在区域内
        for (String regionName : getRegions().keySet()) {
            Rectangle2D regionRect = getRegion(regionName);
            // 注意PDFBox的坐标原点在页面左下角,确保你的区域坐标是正确的
            if (regionRect.contains(text.getX(), text.getY())) {
                regionTextPositions.computeIfAbsent(regionName, k -> new ArrayList<>()).add(text);
            }
        }
    }

    // 获取指定区域的所有文本位置信息(包含字体)
    public List<TextPosition> getTextPositionsForRegion(String regionName) {
        return regionTextPositions.getOrDefault(regionName, Collections.emptyList());
    }
}

使用示例

try (PDDocument document = PDDocument.load(new File("your-file.pdf"))) {
    PDPage page = document.getPage(0); // 假设处理第一页
    RegionTextWithFontStripper stripper = new RegionTextWithFontStripper();
    
    // 添加你的目标区域
    Rectangle2D rect = new Rectangle2D.Double(96, 150, 101, 11);
    stripper.addRegion("selectedText", rect);
    
    stripper.extractRegions(page);
    
    // 获取区域内的所有TextPosition
    List<TextPosition> textPositions = stripper.getTextPositionsForRegion("selectedText");
    for (TextPosition text : textPositions) {
        // 提取字体名称、字号等信息
        String fontName = text.getFont().getName();
        float fontSize = text.getFontSize();
        String content = text.getUnicode();
        System.out.printf("文本:%s,字体:%s,字号:%.1f%n", content, fontName, fontSize);
    }
} catch (IOException e) {
    e.printStackTrace();
}

注意事项

  • 坐标校验:PDFBox的坐标原点在页面左下角,如果你是从其他工具(比如PDF阅读器)获取的坐标,可能需要转换y轴(页面高度 - 原y坐标)才能匹配正确区域。
  • 文本片段:一个完整的单词可能被拆分成多个TextPosition实例,你可能需要根据位置信息合并它们,再统一处理字体。

内容的提问来源于stack exchange,提问作者swarupn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:57:12