如何使用PDFBox提取PDF内容时保留单词间的多空格?
用PDFBox保留PDF原排版(多空格)的文本提取方法
默认PDFBox的文本提取会忽略字符的位置信息,直接按顺序拼接字符,导致原有的多空格排版丢失。要保留排版,需要通过跟踪字符的坐标位置,手动计算字符间的间距并填充空格。
实现步骤
- 自定义
PDFTextStripper子类,重写writeString方法——这个方法可以获取到每个字符的精确位置坐标。 - 跟踪每行字符的X坐标,计算当前字符与前一个字符的水平间距,将间距转换为对应数量的空格。
- 处理换行逻辑,每行开始时重置位置跟踪。
示例代码(Java)
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.io.Writer; import java.util.List; public class LayoutPreservingTextStripper extends PDFTextStripper { private float lastX = -1; private static final float SPACE_PIXEL_WIDTH = 6; // 根据字体调整,默认按6像素对应一个空格 public LayoutPreservingTextStripper() throws IOException { super(); } @Override protected void writeString(String text, List<TextPosition> textPositions) throws IOException { Writer writer = getWriter(); if (writer == null) return; for (int i = 0; i < textPositions.size(); i++) { TextPosition pos = textPositions.get(i); float currentX = pos.getXDirAdj(); // 不是行首,计算与前一个字符的间距,填充空格 if (lastX != -1) { float gap = currentX - lastX - pos.getWidthDirAdj(); if (gap > 1) { // 忽略极小间距 int spaces = (int) Math.round(gap / SPACE_PIXEL_WIDTH); writer.write(" ".repeat(spaces)); } } writer.write(pos.getUnicode()); lastX = currentX + pos.getWidthDirAdj(); } } @Override protected void writeLineSeparator() throws IOException { super.writeLineSeparator(); lastX = -1; // 换行后重置X坐标跟踪 } public static void main(String[] args) throws IOException { try (PDDocument document = PDDocument.load(new File("your-file.pdf"))) { LayoutPreservingTextStripper stripper = new LayoutPreservingTextStripper(); String extractedText = stripper.getText(document); System.out.println(extractedText); } } }
关键说明
SPACE_PIXEL_WIDTH:需要根据PDF中字体的实际空格宽度调整,比如如果原PDF的空格宽度是8像素,就改成8,确保填充的空格和原排版匹配。- 代码通过
TextPosition获取每个字符的X坐标和宽度,计算字符间的空白间距,转换为对应数量的空格填充。 - 换行时重置
lastX,避免跨行计算间距。
效果
使用这个自定义提取器后,提取出的文本会保留原PDF中的多空格排版,接近你期望的输出格式。
内容的提问来源于stack exchange,提问作者iiprateek
相关产品推荐
相关产品推荐

