我正在尝试用Java中的PDFBox编辑pdf的一些内容。问题是,每当我编辑pdf中的任何字符串,并尝试使用Adobe Reader打开它时,最后一行不会出现在新呈现的pdf中。
当我尝试直接从浏览器顶部打开渲染的pdf时,我能够看到最后一行。但是,它以不同的格式编码。我正在使用以下代码编辑pdf的内容:
PDDocument doc = PDDocument.load(FileName);
PDPage page = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
PDStream contents = page.getContents();
PDFStreamParser parser = new PDFStreamParser(contents.getStream());
parser.parse();
List<Object> tokens = parser.getTokens();
for (int j = 0; j < tokens.size(); j++) {
Object next = tokens.get(j);
if (next instanceof PDFOperator) {
PDFOperator op = (PDFOperator) next;
if (op.getOperation().equals("Tj")) {
COSString previous = (COSString) tokens.get(j - 1);
String string = previous.getString();
string = string.replace("@ordnum&", (null != data.getOrderNumber()?data.getOrderNumber():""));
string = string.replace("@shipid&", (null != data.getShipmentId()?data.getShipmentId():""));
string = string.replace("@customer&", (null != data.getCustomerNumber()?data.getCustomerNumber():""));
string = string.replace("@fromname&", (null != data.getFromName()?data.getFromName():""));
tokens.set(j - 1, new COSString(string.trim()));
}
}
}
编辑pdf会删除“有问题?...”这一行。这里有什么问题?我做错了什么吗?
谢谢。
首先,你必须意识到PDF中字符串有两种根本不同的情况
前一种类型使用PDFDocEncoding(类似于Latin1)或带有前导字节顺序标记的UTF-16BE进行编码。方法costring。getString
和构造函数CoString(String)
是为这种字符串设计的。
后一种类型使用为该字符串要呈现的PDF字体定义的编码进行编码。这可能是一些标准化的编码,比如WinAncienceODing(类似于Latin1)或UniGB-UTF16-H(Adobe-GB1字符集的Unicode(UTF-16BE)编码)。但它也可能是一些定制的单字节或多字节编码。标准化和自定义多字节编码都没有字节顺序标记。
在PDF中的页面内容流中,大多数字符串使用WinAnSienceODing(因为这是它们字体的编码)。因为WinPdOnCode方法和WinPdOnCode方法非常相似。
不过,最后一行是使用Idtice-H编码的,它是2字节CID的水平标识映射,即直接引用字体程序中的字符ID的2字节编码,没有任何意义,没有该字体程序。
由于该字符串不以字节顺序标记开头,costring。getString
假定它使用单字节编码PDFDocencode,因此为每个原始的双字节PDF字符串创建两个Java字符串。由于其中一些字符的字符值超出了实际有效的PDFDocEncoding范围,构造函数CoString(String)
创建一个PDF字符串,其中每个中间Java字符都使用一个两字节UTF-16BE字符来表示;此外,还添加了字节顺序标记。
因此,原始PDF字符串(以十六进制编写)
002b004400590048000300540058004800560057004c0052005100560022000300260052
005100570044004600570003005800560003004400570003004b0057005700530056001d
00120012005a005a005a005600110046004c0057005500580056004f0044005100480011
004600520050001200460052005100570044004600570010005800560012
在你的编辑变成
FEFF002B0000004400000059000000480000000300000054000000580000004800000056
000000570000004C00000052000000510000005600000022000000030000002600000052
000000510000005700000044000000460000005700000003000000580000005600000003
0000004400000057000000030000004B00000057000000570000005300000056000002DB
00000012000000120000005A0000005A0000005A0000005600000011000000460000004C
000000570000005500000058000000560000004F00000044000000510000004800000011
000000460000005200000050000000120000004600000052000000510000005700000044
0000004600000057000000100000005800000056
根据PDF查看器的不同,这可能会产生不同的效果。你原来的台词
例如,可能变得传播很广:
或者彻底消失
因此,简而言之,如果需要编辑这样的PDF,请确保只编辑具有类似拉丁文1编码的PDF字符串。
如果您还需要编辑不同编码的PDF字符串,请使用CoString
方法getBytes
将其提取为byte[]
,以适用于相关编码的方式编辑此数组,并使用构造函数CoString(byte[])
从编辑的字节中创建一个新的CoString
。
但即使这样也不是一个好主意。
还有很多其他的陷阱等着你当编辑流像那样
>
而不是e. g.
(@customer&) Tj
您的流可能包含
(@cust) Tj
(omer&) Tj
或
[(@cust) -6 (omer&) ] TJ
甚至
(omer&) Tj
-62 0 Td
(@cust) Tj
因此,如果新模板使用稍微不同的表示,突然替换可能不起作用。
字体只能部分嵌入。如果替换字符的图示符不包括在内,它们将被绘制为间隙。
编辑后的文本绘制操作可能会依赖于前一个操作使用了特定的宽度。你的替代品会破坏原来的布局。
...
本质上,正确编辑通用文档中的流是非常困难的。
而不是像您的@客户这样的内容占位符
表单字段有名称,可以被它们识别。填写它们不会改变内容中的任何内容。
如果你不想让人们事后编辑你的PDF表单字段,你可以将它们标记为只读,甚至将它们展平到内容中。
我已经实现了从pdf中删除图层的功能,但问题是,我在图层上绘制的内容无法删除。下面是我用来删除图层的代码:
我需要比较PDF文档,这些文档是用iText创建的。我实际上设法比较了文件,但我发现了一个微小的差异。 当在像Notepad++这样的编辑器中打开PDF文件时,我可以看到文件末尾有这样的东西:
问题内容: 链接到pdf 当我尝试从上面的pdf中提取文本时,我混合了在evince查看器中不可见的文本和可见的文本。此外,某些所需的文本缺少查看器中未缺少的字符,例如“ FALCONS”中的“ S”和许多缺少的“ 1/2”字符。我认为这是由于来自不可见文本的干扰,因为在查看器中突出显示pdf时,可以看到不可见文本与可见文本重叠。 有没有办法删除不可见的文字?还是有其他解决方案? 码: 输出(粗体
链接到pdf 当我尝试从上面的pdf中提取文本时,我得到了在evince viewer中不可见的文本和可见的文本的混合。此外,一些所需的文本缺少查看器中没有缺少的字符,例如,“FALCONS”中的“S”和许多缺少的“½”字符。我认为这是由于不可见文本的干扰,因为在查看器中突出显示pdf时,可以看到不可见文本与可见文本重叠。 有没有办法去掉不可见的文字?还是有别的解决办法? 代码: 输出(粗体文本为
使用QPDF,您可以简单地从PDF文件中删除限制/加密,如下所示: 我想用Java中的PDFBox做同样的事情: 我已经用尝试过了,但是我不知道所有者密码是什么。QPDF是如何做到这一点的? 示例文档: https://issues.apache.org/jira/secure/attachment/12514714/in.pdf
问题内容: 全部 我正在使用IText在PDF上添加文本层。现在我想编辑PDF上的现有图层,图层也仅由IText创建。似乎IText没有支持这种方法。 我想到的另一种方法是删除现有图层并在其位置放置新图层。似乎IText也不支持删除。有什么办法吗? 非常感谢。 问题答案: 事实证明,所讨论的图层是iText确实称为图层的,但实际上在PDF术语中却称为 可选内容组。 实际上,确实存在一个实用程序类,