生成PDF时无法获得捷克字符
在生成PDF时添加“Č”或“Ć”等字符时遇到问题。 我主要是使用段落插入一些静态文本到我的PDF报告。 以下是我使用的一些示例代码:
var document = new Document(); document.Open(); Paragraph p1 = new Paragraph("Testing of letters Č,Ć,Š,Ž,Đ", new Font(Font.FontFamily.HELVETICA, 10)); document.Add(p1);
生成PDF文件时获得的输出如下所示:“testing字母,,,”,“
由于某些原因,iTextSharp似乎无法识别这些字母,如“Č”和“Ć”。
问题:
首先 ,你似乎不是在谈西里尔字符,而是在使用拉丁字母的中欧和东欧语言。 看看代码页1250和代码页1251之间的区别,了解我的意思。 [注:我已经更新了这个问题,以便它谈论捷克字符,而不是西里尔语。]
第二个观察。 您正在编写包含特殊字符的代码:
"Testing of letters Č,Ć,Š,Ž,Đ"
这是一个不好的做法。 代码文件以纯文本格式存储,可以使用不同的编码进行保存。 从编码中意外切换(例如:将其上传到使用不同编码的版本控制系统)会严重损坏文件的内容。
您应该编写不包含特殊字符的代码,但使用不同的符号。 例如:
"Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110"
这也将确保在使用期望不同编码的编译器编译代码时内容不会被改变。
你的第三个错误是你认为Helvetica是一个知道如何绘制这些字形的字体。 这是一个错误的假设。 你应该使用像Arial.ttf这样的字体文件(或者select任何知道如何绘制这些字形的字体)。
你的第四个错误是你没有embedded字体。 假设您使用本地机器上的字体,并且能够绘制特殊字形,那么您将能够读取本地机器上的文本。 但是,收到文件但没有在本地计算机上使用的字体的人可能无法正确读取文档。
你的第五个错误是你在使用字体的时候没有定义一个编码(这与你的第二个错误有关,但是不同)。
解决scheme:
我写了一个名为CzechExample的小例子,其结果如下PDF: czech.pdf
我添加了相同的文本两次,但使用不同的编码:
public static final String FONT = "resources/fonts/FreeSans.ttf"; public void createPdf(String dest) throws IOException, DocumentException { Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(DEST)); document.open(); Font f1 = FontFactory.getFont(FONT, "Cp1250", true); Paragraph p1 = new Paragraph("Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110", f1); document.add(p1); Font f2 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, true); Paragraph p2 = new Paragraph("Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110", f2); document.add(p2); document.close(); }
为了避免你的第三个错误,我使用了字体FreeSans.ttf而不是Helvetica。 只要支持要使用的字符,您可以select任何其他字体。 为了避免你的第四个错误,我将embedded
参数设置为true
。
至于你的第五个错误,我介绍了两种不同的方法。
在第一种情况下,我告诉iText使用代码页1250。
Font f1 = FontFactory.getFont(FONT, "Cp1250", true);
这会将字体作为简单字体embedded到PDF中,这意味着String
中的每个字符都将使用一个字节来表示。 这种方法的优点是简单; 缺点是你不应该开始混合代码页。 例如:这不适用于西里尔字形。
在第二种情况下,我告诉iText使用Unicode进行横向书写:
Font f2 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, true);
这会将字体作为复合字体embedded到PDF中,这意味着String
中的每个字符都将使用多个字节来表示。 这种方法的优点是它是在较新的PDF标准(例如PDF / A,PDF / UA)中推荐的方法,并且可以将西里尔文与拉丁文,中文与日文等混合使用。缺点是您创build更多的字节,但这种效果受限于内容stream无论如何被压缩的事实。
当我解压缩示例PDF文本的内容stream时,我看到以下PDF语法:
正如我所解释的,单个字节用于存储第一行的文本。 双字节用于存储第二行的文本。
您可能会惊讶于这些字符在外部看起来不错(在Adobe Reader中查看文本时),但与您在内部看到的内容(查看第二个屏幕截图时)不一致,但这就是它的工作原理。
结论:
许多人认为创buildPDF是微不足道的,创buildPDF的工具应该是一种商品。 事实上,并不总是如此简单;-)