如何在使用 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();
}