有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

我做了一些研究,发现我使用的字体(Courier Prime)不支持这些unicode控制字符

那么,当unicode控制字符不受支持时,为什么hasGlyph()会返回true呢?当然,在我进入writeTextWithSymbol()方法之前,我可以用一个简单的replaceAll从行中去掉控制字符,但是如果hasGlyph()方法没有像我预期的那样工作,我就有一个更大的问题

PdfDocumentBuilder:

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());
    }
}

堆栈跟踪:

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)

共 (1) 个答案

  1. # 1 楼答案

    正如上面评论中所解释的,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;
        }
    }