如何在使用 PDFBox 将字符串打印为 PDF 之前对其进行清理
How to sanitise a string before printing it to PDF with PDFBox
我正在根据 UTF-8 用户输入创建 PDF 文档。
除了显示 PDF 之外,创建本身失败 java.lang.IllegalArgumentException: U+039B is not available in this font's encoding: WinAnsiEncoding
。
这里的大多数答案都指向 "using a font with better UTF-8 support",但由于我无法控制用户输入,因此这种 UTF-8 支持永远不够好,我需要一个防弹解决方案(如印刷品而不是错误输出)。
答案 建议在将文本添加到 PDF 之前对其进行清理。
问题是我找不到有效的例子来实现这个。
所有示例似乎都指向已删除的代码(font.setToUnicode
或编码中的某种方法一次转换一个字符)。
所以简而言之,我有一个字符串我想要一个防弹方法将大部分写入PDFBox文档(显然,字体中丢失的字符将被替换或不打印)。
非常感谢,
JM
我结束了一个字符一个字符的清理。
这是我的清理功能的样子。
为了避免重新处理字符,我缓存了每个给定字体的每个字符的可用性。
当代码点在字体中不可用时,我正在尝试 "standard" 替换字符,如果它不可用,我将替换为问号。
这确实效率低下,但我还没有找到另一种更有效的方法来做到这一点,因为我无法控制,也不知道正在打印的内容。
可能有很多地方需要改进,但这适用于我的用例。
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();
}
我正在根据 UTF-8 用户输入创建 PDF 文档。
除了显示 PDF 之外,创建本身失败 java.lang.IllegalArgumentException: U+039B is not available in this font's encoding: WinAnsiEncoding
。
这里的大多数答案都指向 "using a font with better UTF-8 support",但由于我无法控制用户输入,因此这种 UTF-8 支持永远不够好,我需要一个防弹解决方案(如印刷品而不是错误输出)。
答案
问题是我找不到有效的例子来实现这个。
所有示例似乎都指向已删除的代码(font.setToUnicode
或编码中的某种方法一次转换一个字符)。
所以简而言之,我有一个字符串我想要一个防弹方法将大部分写入PDFBox文档(显然,字体中丢失的字符将被替换或不打印)。
非常感谢, JM
我结束了一个字符一个字符的清理。
这是我的清理功能的样子。
为了避免重新处理字符,我缓存了每个给定字体的每个字符的可用性。
当代码点在字体中不可用时,我正在尝试 "standard" 替换字符,如果它不可用,我将替换为问号。
这确实效率低下,但我还没有找到另一种更有效的方法来做到这一点,因为我无法控制,也不知道正在打印的内容。
可能有很多地方需要改进,但这适用于我的用例。
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();
}