解决方法
不幸的是,PDFBox的字符串编码远非完美(版本1.8.x).不幸的是,它在编码通用PDF对象中的字符串时使用相同的例程,就像在内容流中编码字符串时一样,这是根本错误的.因此,您必须自己转换为正确的编码,而不是使用PDPageContentStream.drawString(使用错误的编码).
例如.而不是使用
contentStream.beginText(); contentStream.setTextMatrix(100,100,50,100); contentStream.setFont(PDType1Font.HELVETICA,2); contentStream.drawString("€"); contentStream.endText(); contentStream.close();
结果
你可以使用一些像
contentStream.beginText(); contentStream.setTextMatrix(100,8); byte[] commands = "(x) Tj ".getBytes(); commands[1] = (byte) 128; contentStream.appendRawCommands(commands); contentStream.endText(); contentStream.close();
导致
如果您想知道如何使用128作为€的字节代码,请查看PDF规范ISO 32000-1,附录D.2,拉丁字符集和编码,它们表示€符号的八进制值200(十进制128) WinAnsiEncoding.
PS:其他答案同时提出了一种替代方法,在符号的情况下,如下所示:
contentStream.beginText(); contentStream.setTextMatrix(100,8); contentStream.drawString(String.valueOf(Character.tochars(EncodingManager.INSTANCE.getEncoding(COSName.WIN_ANSI_ENCODING).getCode("Euro")))); contentStream.endText(); contentStream.close();
这确实也画出了”’符号.但即使这种方法看起来更干净(它不使用字节数组,也不会手动构建实际的PDF流操作),它以自己的方式变脏:
要使用破坏的方法,它实际上以正确的方式打破其字符串参数以抵消方法中的错误.
因此,如果PDFBox人员决定修复损坏的PDFBox方法,这里看似干净的解决方法代码将开始失败,因为它将提供固定方法损坏的输入数据.