【问题标题】:Copy PDF to a new PDF, but without certain bits of the document将 PDF 复制到新的 PDF,但没有文档的某些部分
【发布时间】:2020-04-23 13:04:40
【问题描述】:

我正在尝试做一些我知道不是 100% 可靠的事情,但我已经阅读过它,并且据我了解,我在尝试从PDF文件是我无法替换它们。

我想要做的是获取 PDF 文件的内容,然后将该内容复制到另一个 PDF 文件,但没有找到正则表达式。 我在我的 PDF 文件中找到了表达式,并且它有效。

但是,我想不出删除它们的方法。有没有办法说类似

// Remove all TextPosition objects that are within this list

因为我已经收集了它们,但我不明白为什么这不起作用。

或者有没有办法覆盖写入新文件的内容,然后让该覆盖的方法跳过我告诉它跳过的所有文本位置?我见过这样的例子,但当我尝试它们时似乎没有一个有效。 (事实上​​,很多被覆盖的方法甚至似乎根本没有被调用)

【问题讨论】:

  • “我不明白为什么这不起作用” - 这至少很难的一个原因是,在 PDF 中没有 TextPosition 对象.在 PDF 中,您可以找到以任意编码绘制字符串的说明。 PDFBox 解析机制将这些字符串拆分为单个字符,确定它们的位置等,并从中构建一个TextPosition。不幸的是,它没有添加对原始字符串和其中字符位置的引用。因此,为了使代码能够识别 PDF 中匹配的字符串部分,它必须再次进行所有解析并在复制之前进行比较
  • 因此,要实现您的目标,您最好不仅使用TextPosition 对象,而且还要以某种方式将它们链接回它们所来自的字符串。
  • 我明白了。我实际上已经看了很多你的例子,它们真的很好。我可能完全不在这里,但我在任何地方都找不到很多文档。我得到的最好的信息是你的例子和其他一些例子,但我想要更多的例子和解释。 (另外,我知道 Apache 删除了整个替换文本位,因为它非常复杂)我正在攻读这个(以及更多)的学士学位,所以这就是我正在寻找的原因。
  • 我实际上正在使用 HelloAnalyzer 查看您的示例,而您的示例根本不适用于我的 PDF。但我真正需要的是对这些运营商的一些好的指导。我无法像您那样添加运算符,它只是不会添加,因此我的 ContentStreamWriter 为空。
  • 来自this answerHelloAnalyzerHelloSignManipulator 使用了相关文档内容的一种非常特殊的结构,它们作为通用文本编辑的模板并不真正有用。

标签: java pdfbox


【解决方案1】:

我不明白为什么这不起作用

至少很难做到这一点的一个原因是,在 PDF 中没有 TextPosition 对象。

在 PDF 中,您可以找到以任意编码绘制字符串的说明。 PDFBox 解析机制将这些字符串拆分为单个字符,确定它们的位置等,并从中构建一个TextPosition。不幸的是,它没有添加对原始字符串和其中字符位置的引用。

因此,为了让代码能够识别 PDF 中匹配的字符串部分,它必须再次进行所有解析并在复制之前进行比较。

因此,为了实现您的目标,您最好不仅使用TextPosition 对象,而且还要以某种方式将它们链接回它们所来自的字符串。

这在某种程度上超出了堆栈溢出答案的范围,但由于这是您的 BA 工作的(或至少一个)重点,因此体面的尝试可能适合该范围。

因此,我将在这里给出一些建议,让您了解如何开始。

为什么PDFBox没有这样的机制启动?

其实在 PDFBox 发行版(版本 2 之前)中曾经有一个编辑 PDF 文档文本内容的示例。然而,越来越明显的是,这个例子依赖于一些先决条件,因为不满足这些先决条件的文档变得越来越普遍,所以这个例子被删除了,cf. PDFBox 2.0.0 migration guide

您可以在this answer 中找到更详细的关于轻松替换文本的障碍的描述,其精髓在于通用文本替换介于复杂和不可能之间;但是,如果您可以在原始 PDF 中要求某些先决条件,那么您可以要求的越多,就越容易。

不过,在现实生活中,如果您对输入有一定程度的控制,则只能要求此类先决条件,例如如果您只处理某些其他程序的输出并且知道那些其他程序可以满足这些要求。

因此,作为通用库的 PDFBox 删除了简单示例。

一种方法

对于更通用的文本编辑方法,您确实应该尝试将文本删除和文本添加相结合。

对于文本删除,您应该考虑使用类似this answer 中讨论的通用内容流编辑器类PdfContentStreamEditor。但是,当您想使用表示文本的高级 PDFBox 类(如 TextPosition)时,您可能希望基于 PdfTextStripper(使用这些文本位置对象)而不是 PDFGraphicsStreamEngine

在那个专门的文本剥离器/内容编辑器中,您将收集所有正在解析的指令,而不是立即将它们再次写到 write。此外,您可以将processTextPosition 检索到的TextPosition 对象与write 检索到的当前文本绘制指令相关联,以便稍后知道哪个TextPosition 属于哪个文本绘制指令的哪个位置。

解析整个页面后,您可以确定要删除的TextPosition 对象。

一旦知道它们,找到相关的文本绘制指令和位置。现在,您可以拆分每个绘图指令的文本以进行更改,删除要删除的部分,并通过一些位置提升来替换它们(例如,在 TJ 指令的数组参数中使用数字条目)。 p>

一旦所有与要删除的文本位置相关的文本绘制指令都被如此操作,您终于可以将所有指令写入编辑器输出。

之后,您可以照常在相关位置添加新文本。

至少这是我将如何处理更通用的文本编辑器的任务。仍然存在一些挑战;例如内容流编辑器仅编辑单个内容流,而页面文本可能分布在页面内容流和引用的 XObject 内容流(实际上也是模式内容流)中。

根据您预计在 PDF 编辑任务上投入的工作量,您可能需要也可能不需要考虑这些挑战。

文档

在评论中你说你在任何地方都找不到很多文档。显而易见的文档是 PDF 规范、ISO 32000-1 和 ISO 32000-2。如果您的部门经常执行深入的 PDF 任务,他们应该为您提供这些任务。如果没有,您可以在其网站上找到 Adob​​e 发布的 ISO 32000-1 副本(删除了 ISO 标头),只需在 Google 上搜索“PDF32000”即可。

该规范显然没有记录如何替换文本,但它记录了内容流的外观以及其中可能包含哪些指令。

【讨论】:

  • 抱歉回复晚了!这个答案显然是我想要的。我会调查一下。但是,我会说,我设法根据自己的想法、您的示例和其他人的一些尝试和错误来创建一些东西。它首先分析(就像您的示例一样),然后创建一个新的 pdf,其中删除了所需模式的每个提示,然后创建第三个文档,在空白处插入新文本。一些奇怪的事情,比如我必须加载文档 2 次才能正确地从文档中收集信息,但我想还有更多内容需要阅读。
猜你喜欢
  • 2018-04-21
  • 2018-09-22
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 2023-03-31
  • 1970-01-01
  • 2021-03-13
相关资源
最近更新 更多