使用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
相关产品推荐
相关产品推荐

