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

使用PDFBox读取PDF文本出现多余空格,求解决办法

解决PDFBox提取文本出现多余空格的问题

我之前也踩过这个坑!PDFBox的文本提取逻辑有时候会因为PDF内部的字符存储方式(很多PDF里每个字符是单独定位的,而非按单词块存储),误把字符间的正常间距当成空格,导致像“Jeremy Bern stein”这种错误输出。你试过的setAverageCharTolerance和setSpacingTolerance确实对某些PDF管用,但遇到排版特殊的文件就失效了,下面给你几个亲测有效的方案:

方案一:自定义PDFTextStripper,精准控制空格添加逻辑

最靠谱的方式是重写PDFTextStripper的文本处理方法,通过计算字符间的实际水平距离来判断是否真的需要添加空格。比如我们可以把字符间距和当前字符的空格宽度做对比,只有当间距超过阈值时才添加空格:

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.List;

public class CustomPDFTextStripper extends PDFTextStripper {
    public CustomPDFTextStripper() throws IOException {
        super();
    }

    @Override
    protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
        StringBuilder cleanedText = new StringBuilder();
        TextPosition previousChar = null;

        for (TextPosition currentChar : textPositions) {
            if (previousChar != null) {
                // 计算当前字符与上一个字符的水平间距
                float charSpacing = currentChar.getXDirAdj() - (previousChar.getXDirAdj() + previousChar.getWidthDirAdj());
                // 获取当前字体的空格宽度,作为判断空格的阈值
                float spaceWidth = currentChar.getWidthOfSpace();
                
                // 只有当间距超过空格宽度的一半时,才判定为需要添加空格
                if (charSpacing > spaceWidth * 0.5) {
                    cleanedText.append(" ");
                }
            }
            cleanedText.append(currentChar.getUnicode());
            previousChar = currentChar;
        }
        // 写入处理后的文本
        writeString(cleanedText.toString());
    }
}

使用这个自定义Stripper替换原来的PDFTextStripper即可:

PDDocument pdf = null;
try {
    pdf = PDDocument.load(new File(path));
    CustomPDFTextStripper stripper = new CustomPDFTextStripper();
    String extractedText = stripper.getText(pdf);
    // 可选:用正则清理可能残留的连续空格
    extractedText = extractedText.replaceAll("\\s+", " ");
    System.out.println(extractedText);
    pdf.close();
} catch (IOException ioe) {
    ioe.printStackTrace();
}

方案二:换用Apache Tika,借助更成熟的文本提取逻辑

如果自定义Stripper还是麻烦,你可以试试Apache Tika——它底层基于PDFBox,但做了大量的文本提取优化,对这类空格问题处理得更智能:

import org.apache.tika.Tika;
import org.apache.tika.exception.TikaException;

import java.io.File;
import java.io.IOException;

public class TikaPDFExtractor {
    public static void main(String[] args) {
        Tika tika = new Tika();
        try {
            String text = tika.parseToString(new File(path));
            System.out.println(text);
        } catch (IOException | TikaException e) {
            e.printStackTrace();
        }
    }
}

注意需要引入Tika的依赖(比如Maven里添加tika-core和tika-parsers-standard-package)。

为什么之前的tolerance方法没用?

setAverageCharTolerance和setSpacingTolerance是PDFBox早期用来调整空格判断的参数,但它们的逻辑比较简单,只适用于字符间距相对规整的PDF。对于一些采用特殊排版(比如精细调整字符间距的印刷类PDF),这些参数的阈值很难匹配实际情况,所以才会失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:24:47