作为我们自动构建过程的一部分,我们希望在一系列PDF文件(我们的参考指南)中修补内部版本号。干净的方法是自动化LibreOffice中的一些宏来更新字段并再次输出PDF。
但是,我想知道是否存在更直接(但可以说是脏的)解决方案,该解决方案包括在PDF文件中运行一些二进制查找和替换占位符。但是,PDF中的内容似乎没有以明文形式出现。有什么诀窍会有所帮助吗?
答案 0 :(得分:2)
该号码不以明文形式提供,因为它是压缩内容流的一部分。
拿一个“Hello World!”例。表示该文本的内容流可能如下所示:
2 0 obj
<</Length 65/Filter/FlateDecode>>stream
xœ+är
á26S°00SIá2PÐ5´ 1ôÝBÒ¸4<RsròÂó‹rR5C²€j@*\C¸¹ Çq°
endstream
endobj
解压缩二进制部分时,您会发现:
q
BT
36 806 Td
0 -18 Td
/F1 12 Tf
(Hello World!) Tj
0 0 Td
ET
Q
但是,以下语法也是正确的:
BT
/F1 12 Tf
88.66 806 Td
(ld!) Tj
-22 0 Td
(Wor) Tj
-15.33 0 Td
(llo) Tj
-15.33 0 Td
(He) Tj
ET
这种语法难以阅读,但是如果你完成所有数学运算并根据文本矩阵的变化重新组织不同的文本片段,你会发现输出与我们的语法输出完全相同之前。
如果您的PDF是以直接的方式创建的,这意味着可以在解压缩的语法中轻松识别字符串,您可以获取页面的内容流,解压缩,更改,压缩和放置它回到PDF中。
这也假设您要查找的String存在于页面的内容流中,而不是存在于外部内容流中;即:在 Form XObject 。
中如果满足所有这些假设,您可以像这样使用iText:
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
int total = reader.getNumberOfPages() + 1;
for (int i = 1; i < total; i++) {
byte[] content = reader.getPageContent(i);
byte[] alteredBytes = doSomethingWith(content);
reader.setPageContent(i, alteredBytes);
}
stamper.close();
reader.close();
您必须实施doSomethingWith()
方法,以便执行二进制搜索&amp;取代你的需要。
重要提示:您要求快速提供&amp;肮脏的方式,这是一个非常快速的&amp;脏的方式。如果我看到我的一名员工提交此代码,如果他或她不能给我任何合适的论据来使用此代码,我会当场解雇他或她。对于许多PDF,此代码将失败,但它可能正是您在特定用例中所需要的。