使用iText7生成PDF时阿拉伯文显示异常的原因排查
iText7 阿拉伯文PDF显示异常问题排查
一、代码实现
1. PDF模板读取与文本添加代码
PdfReader reader = new PdfReader(PdfUtil.class.getClassLoader().getResourceAsStream(docsDownloadConfig.getStatementTemplatePath())); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfWriter writer = new PdfWriter(baos); PdfDocument pdfDoc = new PdfDocument(reader, writer); Document document = new Document(pdfDoc, PageSize.A4); pdfDoc.setDefaultPageSize(PageSize.A4); String arString = user.getName; document.add(new Paragraph(reorderArabicText(arString)).setFont(getFont())); document.close(); return baos;
2. 阿拉伯文重排方法
private static String reorderArabicText(String text) { Pattern arabicPattern = Pattern.compile("[\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF\\uFB50-\\uFDFF\\uFE70-\\uFEFF]+"); if (arabicPattern.matcher(text).find()) { Bidi bidi = new Bidi(text, Bidi.DIRECTION_RIGHT_TO_LEFT); bidi.setReorderingMode(Bidi.REORDER_INVERSE_NUMBERS_AS_L); return bidi.writeReordered(Bidi.DO_MIRRORING); } else return text; }
3. 字体获取方法
private static PdfFont getFont() throws IOException { return PdfFontFactory.createFont("images/NotoNaskhArabic-Regular.ttf", PdfEncodings.IDENTITY_H); }
4. 依赖配置
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>8.0.4</version> <type>pom</type> </dependency> <dependency> <groupId>com.ibm.icu</groupId> <artifactId>icu4j</artifactId> <version>75.1</version> </dependency>
二、问题现象
阿拉伯文存在两种输入来源,表现出明显差异:
- 来源1:从Word模板复制存入MySQL(字符集utf8mb4,排序规则utf8mb4_09000_ai_ci),在MySQL Workbench中显示为方块,但生成PDF显示正常。
- 来源2:读取数据库中已有数据,在MySQL Workbench中显示正常,但生成PDF显示异常。
- 两种数据的二进制值不同,但用
CharsetDetector检测编码结果均为UTF-8。
三、疑问
iText是否会根据文本编码来决定阿拉伯文能否正确显示?该异常现象的原因是什么?
解答
iText 不直接根据文本编码(Java 字符串统一采用 UTF-16 存储)决定阿拉伯文的显示效果,核心影响因素是文本的 Unicode 字符形态和双向文本(Bidi)处理逻辑。
异常原因拆解:
两种数据的 Unicode 字符本质不同:
- 来源1的Word复制数据:属于阿拉伯文的预组合连字字符(对应 Unicode Presentation Forms-A/B 区块,如
\uFB50-\uFDFF),这类字符是预先组合好的视觉形态,无需额外的Bidi重排即可正确渲染,且你使用的NotoNaskhArabic字体支持这类字符,因此PDF显示正常。MySQL Workbench显示方块是因为其默认字体不支持这些特殊的预组合字符。 - 来源2的数据库已有数据:属于阿拉伯文的标准逻辑字符(对应 Unicode Arabic 区块,如
\u0600-\u06FF),这类字符需要通过Bidi处理将逻辑顺序转换为视觉顺序才能正确显示。但你的代码中强制设置了Bidi.DIRECTION_RIGHT_TO_LEFT,如果该数据本身已经是视觉顺序存储(而非逻辑顺序),再次经过Bidi重排会导致字符顺序反转,最终PDF显示异常。
- 来源1的Word复制数据:属于阿拉伯文的预组合连字字符(对应 Unicode Presentation Forms-A/B 区块,如
编码检测无法区分字符形态差异:两种数据的字节序列都符合UTF-8编码规则,但Unicode字符点完全不同,因此二进制值不一样,编码检测工具只能识别字节编码格式,无法区分字符形态的差异。
内容的提问来源于stack exchange,提问作者L.G
相关产品推荐
相关产品推荐

