请看一下NameObject示例,并试一试。您会看到 iText 自动转义名称中的特殊字符。
iText 遵循 ISO-32000-1 规范,该规范统计(7.3.5,名称对象):
从 PDF 1.2 开始,名称对象是由除 null(字符代码 0)之外的任何字符(8 位值)序列唯一定义的原子符号。唯一定义意味着任何两个由相同字符序列组成的名称对象表示同一个对象。原子意味着名称没有内部结构;尽管它是由一系列字符定义的,但这些字符不被视为名称的元素。
不是名称的一部分,而是一个前缀,表示后面是代表 PDF 文件中名称的字符序列,并应遵循以下规则:
a) 名称中的数字符号 (23h) (#) 应使用其前面的数字符号的 2 位十六进制代码 (23) 写入。
b) 名称中的任何常规字符(除数字符号外)的任何字符都应直接写入或使用其前面的数字符号的 2 位十六进制代码。
c) 任何不是常规字符的字符都应使用其 2 位十六进制代码写入,仅以数字符号开头。
注意 1:PDF 文件中的名称没有唯一的编码,因为常规字符可能以两种方式中的任何一种进行编码。
用作名称一部分的空格应始终使用 2 位十六进制符号进行编码,并且 SOLIDUS 和编码名称之间不得插入空格。
超出 EXCLAMATION MARK(21h) (!) 到 TILDE (7Eh) (~) 范围的常规字符应使用十六进制表示法写入。
令牌 SOLIDUS(后跟没有常规字符的斜线)引入了由空字符序列定义的唯一有效名称。
注 2 表 4 中显示的包含 # 的示例在 PDF 1.0 或 1.1 中不是有效的文字名称。
我不是复制/粘贴表 4,但我没有看到任何使用由两个字节组成的字符的示例。您能否共享一个 PDF,其中包含一个名称和两个字节字符,其行为方式符合您的要求?PDF 规范明确指出名称上下文中的字符是 8 位值。您似乎在谈论 16 位值...
附加说明:在当前的 iText 实现中,我们只看 8 位:
c = (char)(chars[k] & 0xff);
当传递超过 8 位的字符时,我们故意丢弃所有高位。
事实上,我想我已经回答了你的问题。最初,我以为您要求添加此字符:http ://www.fileformat.info/info/unicode/char/c3a4/index.htm
事实证明,您只需要"\u00e4"
(ä)。我制作了一个小代码示例,演示如何将自定义条目添加到包含此字符的 DID:ChangeInfoDictionary。
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
Map<String, String> info = reader.getInfo();
info.put("Special Character: \u00e4", "\u00e4");
stamper.setMoreInfo(info);
stamper.close();
reader.close();
}
当然,当您在 PDF 查看器中打开 PDF 时,您不一定会看到“特殊字符:ä”作为键值,但这是 PDF 查看器的问题。当您在文本编辑器中打开 PDF 时,您会清楚地看到:
/Special#20Character:#20#e4(ä)
这意味着 iText 已正确转义了特殊字符。
但是:正如您在评论中指出的那样,该角色不会出现在 Adobe Reader 中。根据我使用 Acrobat 创建的 PDF,我找到了使用以下代码的解决方法:
StringBuffer buf = new StringBuffer();
buf.append((char) 0xc3);
buf.append((char) 0xa4);
info.put(buf.toString(), "\u00e4");
现在字符显示正确。换句话说:这是一个编码问题......