为什么会在 pdf 中发生这种情况?
您看到的作为最终静态图像的 PDF 页面的内容是按照其内容流中的一系列指令绘制的。这些指令主要要么设置一些属性(颜色、字体,...),要么实际绘制一些东西(“从 A 到 B 画一条线”,“从 B 开始绘制文本字符串 A”,...)。 PDF 标准不要求按阅读顺序排列这些说明,例如字符串“Hello world”可以先绘制“world”再绘制“Hello”。
默认情况下,PDFBox 文本剥离器按绘制顺序提取文本。例如。假设在您的页面上有四个文本片段 A、B、C 和 D 明显按该顺序排列,但按 A、C、D 和 B 顺序绘制。PDFBox 默认情况下将按后一顺序 A、C 提取它们、D 和 B。(如果你要求它排序,你会按从上到下、从左到右的顺序得到它。)
Adobe Reader 还按照绘制顺序标记文本。例如。再次假设在您的页面上有四个文本片段 A、B、C 和 D 明显按该顺序排列,但按 A、C、D 和 B 顺序绘制。如果您从 A 到 C 标记,则不会标记 B , 只有 A 和 C。
例如您的 PDF
您文档的第 2 页确实以有趣的顺序绘制:
这解释了你的观察:
标记文本的开头和结尾以 Xobject 的形式绘制。因此,只有 Xobject 表单中的文本被标记,而不是页面内容流中稍后绘制的两个段落。
顺便说一句,如果您想知道为什么文本看起来像位图扫描图像,尽管它是作为文本绘制的......这里使用的字体是从扫描页面中通过切割小块构建而成的,其中包含OCR 机制被认为是单个字形。这有时并不完全对应于单个字符,该字体中的某些字形对应于多个字符:
如您所见,对于某些字符,字体中有多个字形(例如小写“o”),而某些字形包含多个字符(例如“es”或“mi”)。
解决这个问题的方法是什么? (除了在 PDFStripper 中读取设置 readSorted 为 true)
好吧,你必须决定你想要什么。您希望文本按绘制顺序排列,或者按排序顺序排列。
如果你希望它按绘图顺序,每隔一段时间就会有文档以文本块的顺序出现这种不稳定的跳跃。
如果您希望它以不同的顺序排列,则必须进行排序。 PDFBox 提供的排序是简单的从上到下、从左到右的排序。如果您有不同的排序方式,您可以从文本剥离器中检索 TextPosition 对象,它在其中存储字形以及它们在页面上的位置、大小和方向,然后自行对它们进行排序。
如何在 java 中以编程方式检测到这一点?有哪些潜在的方法?
“这个”到底是什么意思?
-
你的意思是文字绘制指令不是从上到下、从左到右绘制的吗?
为此,您可以简单地覆盖PDFTextStripper 方法processTextPosition(TextPosition) 或writeString(String, List<TextPosition>) 并分析TextPosition 实例中的位置。如果他们突然向上跳或(在同一条线上)向左跳,你就会发现这种情况。
-
或者你的意思是文字绘制说明没有按阅读顺序绘制?
这很困难,有多种情况下阅读顺序会再次跳升,例如在多列文本或插入文本框的情况下。这绝对超出了堆栈溢出的答案。