我正在使用UTF-8的用户输入创建PDF文档。
除了显示PDF之外,创建本身也失败了java.lang.IllegalArgumentException: U+039B is not available in this font's encoding: WinAnsiEncoding
。
这里的大多数答案都指向“使用支持更好UTF-8的字体”,但由于我无法控制用户输入,因此这种UTF-8支持永远不会足够好,我需要一个防弹解决方案(就像打印一些东西而不是错误一样。)
答案Using PDFBox to write unicode strings to a PDF表明在将文本添加到PDF之前应对文本进行清理。
问题是我找不到有效的例子来实现这一点。
所有示例似乎都指向已删除的代码(font.setToUnicode
或某些编码方法,以便一次转换一个字符)。
简而言之,我有一个字符串我想要一个防弹方法将大部分写入PDFBox文档(显然,字体中缺少的字符将被替换或不打印)。
非常感谢, JM
答案 0 :(得分:0)
我结束了角色消毒的角色。
这就是我的清理功能。
为了避免重新处理字符,我正在为每个给定字体缓存每个字符的可用性。
当代码点没有字体时,我正在尝试"标准"替换字符,如果不可用,我将替换为问号。
这确实是效率低下的,但我还没有找到另一种更有效的方法,因为我没有控制权,也没有预先知道所印刷的内容。
可能有很多事情需要改进,但这适用于我的用例。
private String getPrintableString(String string, PDFont font) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
int codePoint = string.codePointAt(i);
if (codePoint == 0x000A) {
sb.appendCodePoint(codePoint);
continue;
}
String fontName = font.getName();
int cpKey = fontName.hashCode();
cpKey = 31 * cpKey + codePoint;
if (codePointAvailCache.get(cpKey) == null) {
try {
font.encode(string.substring(i, i + 1));
codePointAvailCache.put(cpKey, true);
} catch (Exception e) {
codePointAvailCache.put(cpKey, false);
}
}
if (!codePointAvailCache.get(cpKey)) {
// Need to make sure our font has a replacement character
try {
codePoint = 0xFFFD;
font.encode(new String(new int[] { codePoint }, 0, 1));
} catch (Exception e) {
codePoint = 0x003F;
}
}
sb.appendCodePoint(codePoint);
}
return sb.toString();
}