对于不受支持的 unicode 控制字符,PDFBox hasGlyph() 返回 true

Kat*_*ett 5 java unicode pdfbox

我正在使用 Apache 的 PDFBox 库来编写 PdfDocumentBuilder 类。currentFont.hasGlyph(character)在尝试将字符写入文件之前,我使用它来检查字符是否具有字形。问题是,当字符是 unicode 控制字符时'\u001f'hasGlyph()返回 true,导致encode()写入时抛出异常(请参阅下面的 PdfDocumentBuilder 代码和堆栈跟踪以供参考)。

我做了一些研究,看起来我使用的字体(Courier Prime)不支持这些 un​​icode 控制字符。

那么为什么hasGlyph()在不支持 unicode 控制字符时返回 true 呢?当然,我可以replaceAll在进入该writeTextWithSymbol()方法之前使用简单的命令从行中删除控制字符,但是如果该hasGlyph()方法没有按我预期的那样工作,我就会遇到更大的问题。

PDF文档生成器:

private final PDType0Font baseFont;
private PDType0Font currentFont;   

public PdfDocumentBuilder () {
    baseFont = PDType0Font.load(doc, this.getClass().getResourceAsStream("/CourierPrime.ttf"));
    currentFont = baseFont;
}

private void writeTextWithSymbol (String text) throws IOException {
    StringBuilder nonSymbolBuffer = new StringBuilder();
    for (char character : text.toCharArray()) {
        if (currentFont.hasGlyph(character)) {
            nonSymbolBuffer.append(character);
        } else {
            //handling writing line with symbols...
        }
    }
    if (nonSymbolBuffer.length() > 0) {
        content.showText(nonSymbolBuffer.toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪:

java.lang.IllegalArgumentException: No glyph for U+001F in font CourierPrime
at org.apache.pdfbox.pdmodel.font.PDCIDFontType2.encode(PDCIDFontType2.java:400)
at org.apache.pdfbox.pdmodel.font.PDType0Font.encode(PDType0Font.java:351)
at org.apache.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:316)
at org.apache.pdfbox.pdmodel.PDPageContentStream.showText(PDPageContentStream.java:414)
at org.main.export.PdfDocumentBuilder.writeTextWithSymbol(PdfDocumentBuilder.java:193)
Run Code Online (Sandbox Code Playgroud)

Kat*_*ett 8

正如上面的评论中所解释的,hasGlyph()并不意味着接受 unicode 字符作为参数。所以如果你需要在写一个字符之前检查它是否可以编码,你可以这样做:

private void writeTextWithSymbol (String text) throws IOException {
    StringBuilder nonSymbolBuffer = new StringBuilder();
    for (char character : text.toCharArray()) {
        if (isCharacterEncodeable(character)) {
            nonSymbolBuffer.append(character);
        } else {
            //handle writing line with symbols...
        }
    }
    if (nonSymbolBuffer.length() > 0) {
        content.showText(nonSymbolBuffer.toString());
    }
}

private boolean isCharacterEncodeable (char character) throws IOException {
    try {
        currentFont.encode(Character.toString(character));
        return true;
    } catch (IllegalArgumentException iae) {
        LOGGER.trace("Character cannot be encoded", iae);
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)