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

时间:2017-03-03 16:53:47

标签: java unicode pdfbox

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

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

那么为什么hasGlyph()在不支持unicode控制字符时会返回true?当然,在我输入replaceAll方法之前,我可以使用简单的writeTextWithSymbol()从行中删除控制字符,但如果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 个答案:

答案 0 :(得分:4)

正如上面的评论中所解释的,using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { char choice = '7'; while (choice != '3') { Console.WriteLine("---------------Calculator---------------"); Console.WriteLine("\n1.Add\n2.Subtract\n3.Multiply\n4.Divide\n5.Modulo-Operation (remainder)\n6.Exit\n"); Console.WriteLine("Enter your choice:"); choice = Convert.ToChar(Console.Read()); switch (choice) { case '1': Calculator.Add(); break; case '2': Calculator.Subtract(); break; case '3': Calculator.Multiply(); break; case '4': Calculator.Divide(); break; case '5': Calculator.Modulo(); break; case '6': Environment.Exit(0); break; default: Console.WriteLine("Invalid Choice.\n"); break; } } } } class Calculator { public static void Add() { int a, b; string sa, sb; Console.WriteLine("Enter the first number:\n"); sa = Console.ReadLine().Trim(); a = Convert.ToInt32(sa); Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); Console.Write("{0}\n", a + b); } public static void Subtract() { int a, b; string sa, sb; Console.WriteLine("Enter the first number:\n"); sa = Console.ReadLine().Trim(); a = Convert.ToInt32(sa); Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); Console.Write("{0}\n", a - b); } public static void Multiply() { int a, b; string sa, sb; Console.WriteLine("Enter the first number:\n"); sa = Console.ReadLine().Trim(); a = Convert.ToInt32(sa); Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); Console.Write("{0}\n", a * b); } public static void Divide() { int a, b; string sa,sb; Console.WriteLine("Enter the first number:\n"); sa = Console.ReadLine().Trim(); a = Convert.ToInt32(sa); Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); while (b == 0) { Console.WriteLine("In division operation, divisor cannot be zero.\n Retry!!\n"); Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); } Console.Write("{0}\n", a / b); } public static void Modulo() { int a, b; string sa, sb; Console.WriteLine("Enter the first number:\n"); sa = Console.ReadLine().Trim(); a = Convert.ToInt32(sa); while (a < 0) { Console.WriteLine("In modulo operation, first number cannot be negative.\n Retry!!\n"); Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); } Console.WriteLine("Enter the second number:\n"); sb = Console.ReadLine().Trim(); b = Convert.ToInt32(sb); Console.Write("{0}\n", a % b); } } } 并不意味着接受unicode字符作为参数。因此,如果您需要在编写字符之前检查字符是否可以编码,您可以执行以下操作:

hasGlyph()