Java 解析PDF时出现奇怪的空白

Java 解析PDF时出现奇怪的空白,java,pdf,whitespace,itext,pdf-parsing,Java,Pdf,Whitespace,Itext,Pdf Parsing,我需要解析一个PDF文档。我已经实现了解析器并使用了库iText,到目前为止,它工作起来没有任何问题 但是,我不需要分析另一个文档,它在单词中间有非常奇怪的空白。例如,我得到: Vo rber eitungauf die电机驱动装置。Viele汽车adf ahr 所有粗体字都应该连接起来,但PDF解析器不知何故在字中添加了空格。但是,当我将PDF中的内容复制并粘贴到文本文件中时,我不会得到这些空格 首先,我认为这是因为我使用的PDF解析库,但也因为另一个库,我得到了完全相同的问题 我从解析的单词

我需要解析一个PDF文档。我已经实现了解析器并使用了库iText,到目前为止,它工作起来没有任何问题

但是,我不需要分析另一个文档,它在单词中间有非常奇怪的空白。例如,我得到:

Vo rber eitungauf die电机驱动装置。Viele汽车adf ahr

所有粗体字都应该连接起来,但PDF解析器不知何故在字中添加了空格。但是,当我将PDF中的内容复制并粘贴到文本文件中时,我不会得到这些空格

首先,我认为这是因为我使用的PDF解析库,但也因为另一个库,我得到了完全相同的问题

我从解析的单词中查看了
singleSpaceWidth
,我注意到它在添加空格时总是变化的。我试着手动把它们放在一起。但是,由于没有一个真正的模式来重组这些词,这几乎是不可能的

有没有其他人有类似的问题,或者甚至有解决这个问题的方法

根据要求,以下是更多信息:

  • iText版本5.2.1
  • (链接至pdf)
使用SemTextExtractionStrategy进行解析:

PdfReader reader = new PdfReader("data/SpecialTests/SuedostSchweiz/" + src);

SemTextExtractionStrategy semTextExtractionStrategy = new SemTextExtractionStrategy();

for (int i = 1; i <= reader.getNumberOfPages(); i++) {
    // Set the page number on the strategy. Is used in the Parsing strategies.
    semTextExtractionStrategy.pageNumber = i;

    // Parse text from page
    PdfTextExtractor.getTextFromPage(reader, i, semTextExtractionStrategy);
}
下面是整个SemTextExtraction类,但在其中它只从上面调用方法(parseText):

公共类SemTextExtractionStrategy实现TextExtractionStrategy{
//文本抽取策略
public ColumnDetecter ColumnDetecter=新ColumnDetecter();
//图像提取策略
public ImageRetriever ImageRetriever=新的ImageRetriever();
公共整数页码=-1;
public ArrayList textParsingStrategies=new ArrayList();
public ArrayList imageParsingStrategies=new ArrayList();
公共SemTextExtractionStrategy(){
//添加稍后应用于提取文本的所有文本解析策略
//textParsingStrategies.add(fontSizeMatcher);
textParsingStrategies.add(columnDetecter);
//添加所有图像解析策略,这些策略稍后将应用于提取的文本
imageParsingStrategies.add(imageRetriever);
}
@凌驾
public void beginTextBlock(){
}
@凌驾
公共void renderText(TextRenderInfo renderInfo){
//文本分析
for(TextParsingStrategy战略:textParsingStrategies){
解析文本(renderInfo,页码);
}
}
@凌驾
public void endTextBlock(){
}
@凌驾
公共无效渲染图像(ImageRenderInfo renderInfo){
for(ImageParsingStrategy:imageParsingStrategies){
策略.parseImage(renderInfo);
}
}
}

因为您拥有的文档被拆分为列,所以明显的错误在

SemTextExtractionsStrategy

班级。我假设类ColumnDetector可能是应该受到责备的对象,而不是iText。我只能假设它是根据列的大小实现的,然后根据该大小检索文本


如果只需要文本,那么根据列的大小,实现可能会更简单。

我已使用以下命令处理给定的PDF文件:

此命令创建了一个文件
out.pdf
,该文件没有流编码,因此可读性更好。有趣的部分在第52行,为了便于阅读,我将其分为多行:

[
  (&;&)-287.988
  (672744)29.9906
  (+\(%)30.01
  (+!4)29.9876
  (&4)-287.989
  (%4)30.0039
  (&1&8)-287.975
  (3=\)!)-288.021
  (*&4)30.0212
  (&=23)-287.996
  (+1%)-287.99
  (\(=&)-288.011
  (8&1&)-287.974
  (672744)29.9906
  (+\(3+=378$)-250.977
  (#7\)!)
]TJ
括号之间是文本字符。我改变了其中一些,并观看了呈现的PDF文件,以查看哪个字符代表哪个字形。然后我解码了文本:

[
  (ele)-287.988
  (Motorr)29.9906 ***
  (adf)30.01 ***
  (ahr)29.9876 ***
  (er)-287.989
  (fr)30.0039
  (euen)-287.975
  (sich)-288.021
  ...
]

因此,字符之间确实存在空白。在您的情况下,这可能是字体的字距调整。现在的问题是您的PDF库如何解释此空白,在我看来,即使是“负空白”也会被呈现到结果字符串中的一个空格中。

PDF中的空白是一个已知的问题,正如Roland在这里的回答中所描述的,在

对我来说同样有效的答案是huuhungus在

这是特定于PDFParser的,如果您知道会出现以下问题,则需要更改代码,以实际将此额外空间添加到PDFParser:

src/Smalot/PdfParser/Object.php注释掉这一行

   $text .= ' ';
虽然没有完全修复,但可以接受


其他库也可能有类似的临时修复程序,以便在某些情况下可以帮助解决此问题。

请告知您正在使用的iText版本,并以某种方式提供PDF,还有你解析的代码。在上面的帖子中添加了所有信息。你使用的TextExtractionStrategy类呢?@Prine你解决了这个问题吗?@tobaiasjl那是很久以前的事了。。但我有点在我的后脑勺PDF已损坏,并与新生成的PDF问题没有发生..谢谢你的回答。我一定会调查一下ColumnDetector。但是parseText方法来自这个类,在那里我直接从iText库中得到输出,在那里单词已经被拆分。有没有办法摆脱这个或实现?你用什么工具来生成pdf?它是Ghostscript;我对答案进行了编辑,以澄清这一点。谢谢你的提示。没有办法去除PDF文件中的空白,因为它就在那里。我不知道iText是否能处理这个问题以及如何处理,因为我不知道iText。在这个回答中,我刚刚解释了附加空格的来源。iText 5.2.1现在是一个古老的版本。当前版本具有属性/可重写方法,可在哪些情况下对iText添加空格,哪些情况下不添加空格进行微调。从不添加空格也是一个糟糕的选择,一般来说,许多PDF文件都会在几乎没有空格的情况下提取文本。
[
  (&;&)-287.988
  (672744)29.9906
  (+\(%)30.01
  (+!4)29.9876
  (&4)-287.989
  (%4)30.0039
  (&1&8)-287.975
  (3=\)!)-288.021
  (*&4)30.0212
  (&=23)-287.996
  (+1%)-287.99
  (\(=&)-288.011
  (8&1&)-287.974
  (672744)29.9906
  (+\(3+=378$)-250.977
  (#7\)!)
]TJ
[
  (ele)-287.988
  (Motorr)29.9906 ***
  (adf)30.01 ***
  (ahr)29.9876 ***
  (er)-287.989
  (fr)30.0039
  (euen)-287.975
  (sich)-288.021
  ...
]
   $text .= ' ';