You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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)处理逻辑。

异常原因拆解:

  1. 两种数据的 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显示异常。
  2. 编码检测无法区分字符形态差异:两种数据的字节序列都符合UTF-8编码规则,但Unicode字符点完全不同,因此二进制值不一样,编码检测工具只能识别字节编码格式,无法区分字符形态的差异。


内容的提问来源于stack exchange,提问作者L.G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:47:33