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

如何在Java中使用PdfBox提取PDF文本时获取行号?

使用PdfBox提取文本并获取行号及相关疑问解答

一、提取带行号的文本实现方案

直接调用getText()只能拿到纯文本,要同时获取行号,需要自定义PDFTextStripper子类,重写writeString方法——该方法可获取每个文本片段的坐标信息,我们通过y坐标的相似度判断文本是否属于同一行(PDF坐标系中y轴向上,同一视觉行的文本y坐标会高度接近)。

示例代码:

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.ArrayList;
import java.util.List;

public class LineNumberTextStripper extends PDFTextStripper {
    private List<String> lineTexts = new ArrayList<>();
    private float currentLineY = -1;
    private static final float Y_TOLERANCE = 2f; // 同一行y坐标误差容忍度,可根据PDF排版调整

    public LineNumberTextStripper() throws IOException {
        super();
    }

    @Override
    protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
        TextPosition firstPos = textPositions.get(0);
        float textY = firstPos.getY();

        // 判断当前文本是否属于新行
        if (currentLineY == -1 || Math.abs(textY - currentLineY) > Y_TOLERANCE) {
            currentLineY = textY;
            lineTexts.add(text);
        } else {
            // 同一行,追加文本
            String lastLine = lineTexts.get(lineTexts.size() - 1);
            lineTexts.set(lineTexts.size() - 1, lastLine + text);
        }
    }

    public List<String> getLineTexts() {
        return lineTexts;
    }

    public static void main(String[] args) throws IOException {
        try (PDDocument document = PDDocument.load(new File("your-document.pdf"))) {
            LineNumberTextStripper stripper = new LineNumberTextStripper();
            stripper.getText(document);

            // 输出带行号的文本
            for (int i = 0; i < stripper.getLineTexts().size(); i++) {
                System.out.printf("行%d: %s%n", i + 1, stripper.getLineTexts().get(i));
            }
        }
    }
}

说明:

  • Y_TOLERANCE是同一行的y坐标误差阈值,不同PDF的字体大小、行间距不同,需根据实际情况微调。
  • 该方案基于视觉行判断,与PDF的实际渲染逻辑一致,因为PDF本身没有结构化的“行”定义。

二、为何PdfBox和iText无直接获取行号的方法?

核心原因是PDF文档本身不存在“行”的结构化概念:

  • PDF是页面描述语言,仅记录每个文本片段的坐标、字体、大小等渲染参数,不会定义“这是第几行”。视觉上的“行”是多个文本片段在y坐标接近时的视觉组合,不同场景对“行”的定义差异极大(比如换行但属于同一逻辑行、同一行被拆分为多个文本块等)。
  • 类库的设计原则是提供底层文本提取能力,将“行的判断逻辑”交给开发者——没有通用的行定义能覆盖所有PDF场景,强行封装行号方法会导致逻辑不符合开发者的实际需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:30:44