Java 如何在使用PDFBox将字符串打印为PDF之前对其进行消毒

Java 如何在使用PDFBox将字符串打印为PDF之前对其进行消毒,java,pdf,encoding,utf-8,pdfbox,Java,Pdf,Encoding,Utf 8,Pdfbox,我正在从UTF-8用户输入创建PDF文档 除了显示PDF之外,创建本身也会失败,原因是java.lang.IllegalArgumentException:U+039B在此字体的编码中不可用:winansienceoding 这里的大多数答案都指向“使用具有更好UTF-8支持的字体”,但由于我无法控制用户输入,这种UTF-8支持永远都不够好,我需要一个防弹解决方案(比如打印一些东西而不是出错) 答案是,在将文本添加到PDF之前,应该对其进行消毒 问题是我找不到有效的例子来实现这一点。 所有的例子

我正在从UTF-8用户输入创建PDF文档

除了显示PDF之外,创建本身也会失败,原因是
java.lang.IllegalArgumentException:U+039B在此字体的编码中不可用:winansienceoding

这里的大多数答案都指向“使用具有更好UTF-8支持的字体”,但由于我无法控制用户输入,这种UTF-8支持永远都不够好,我需要一个防弹解决方案(比如打印一些东西而不是出错)

答案是,在将文本添加到PDF之前,应该对其进行消毒

问题是我找不到有效的例子来实现这一点。 所有的例子似乎都指向删除的代码(
font.setToUnicode
或某种编码方法,一次转换一个字符)

简而言之,我有一个字符串,我想要一个防弹方法将它的大部分写入PDFBox文档(显然,字体中缺少的字符将被替换或不打印)

非常感谢,,
JM

我结束了一个字符一个字符的清理

这里是我的消毒功能的样子

为了避免重新处理字符,我正在缓存每个给定字体的每个字符的可用性

当字体中的代码点不可用时,我将尝试使用“标准”替换字符,如果不可用,我将使用问号替换

这确实是低效的,但我还没有找到另一种更有效的方法来做到这一点,因为我没有控制权,也不知道正在打印什么

可能有很多地方需要改进,但这对我的用例是有效的

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();
}
私有字符串getPrintableString(字符串字符串,PDFont){
StringBuilder sb=新的StringBuilder();
对于(int i=0;i
您使用哪个PDFBox版本?正如你提到的答案,版本1.8。x和2.0.xi-AM使用2.0.3(最后一个版本)的情况不同。你使用哪种字体?你如何使用它?Pdfbox 2.0.x允许您嵌入包含所需字形的字体子集。@mkl是的,我尝试了Ubuntu字体,这在一定程度上改进了一些东西,但它永远都不够好,因为我无法提前知道将打印哪些字符。我正在打印用户输入的文本,基本上他们可以访问整个UTF-8集。有没有办法知道字体中的字形代表什么代码点?这将是非常低效的,但我可以扫描所有字符串,并用PlaceHLoder替换丢失的字符。。。这有助于删除不可打印的字符