最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java生成PDF時該如何正確支持中文生僻字詳解

 更新時間:2026年03月02日 10:03:10   作者:yeye19891224  
這篇文章主要介紹了Java生成PDF時該如何正確支持中文生僻字的相關(guān)資料,包括字體選擇、字體加載、HTML/CSS使用等方面,并提供了一個標(biāo)準(zhǔn)方案來解決生僻字問題,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下

——從字體原理到工程落地的完整實(shí)踐指南

一、問題背景:為什么“生僻字”在 PDF 中總是出問題?

在 Java 項(xiàng)目中使用 iText / OpenPDF / Flying Saucer 生成 PDF,是非常常見的需求,典型場景包括:

  • 合同 / 協(xié)議生成
  • 電子檔案
  • 報表導(dǎo)出
  • 存證類文件

但一旦涉及中文生僻字(如姓名、地名、少數(shù)民族用字、古籍用字),就很容易出現(xiàn)以下問題:

  • PDF 中顯示為
  • 直接空白
  • 只有數(shù)字、符號、序號,中文正文消失
  • 本機(jī)正常,換一臺機(jī)器就亂碼

這些問題并不是 iText 的 bug,而是對 PDF 字體機(jī)制 + 中文字符集 理解不足導(dǎo)致的。

二、核心結(jié)論先行(非常重要)

Java 生成 PDF 要支持中文生僻字,本質(zhì)上只取決于三件事:

  1. 字體是否真正包含該字符(Glyph 是否存在)
  2. PDF 是否使用了該字體(CSS / font-family)
  3. 字體是否隨 PDF 一起嵌入(EMBEDDED)

只要其中任意一個不滿足,生僻字一定失敗。

三、為什么宋體(SimSun)無法支持生僻字?

1. SimSun 的歷史定位

SimSun.ttc(宋體)是一個非常早期的中文字庫,主要覆蓋:

  • GB2312 / GBK
  • 常用漢字

但它不包含

  • CJK 擴(kuò)展區(qū) A / B / C / D / E / F
  • 大量現(xiàn)代姓名用字(如:??、??)
  • 古籍、少數(shù)民族漢字

2. 結(jié)論

宋體不是“壞字體”,而是“時代局限字體”
它從設(shè)計之初就沒打算覆蓋 Unicode 全中文字符集。

因此:

  • Word 里能顯示 ≠ PDF 一定能顯示
  • 系統(tǒng)里有 ≠ 所有人機(jī)器都有

四、真正支持生僻字的字體:Noto / 思源系列

1. 推薦字體

在 Java PDF 場景中,強(qiáng)烈推薦使用靜態(tài)版本的 Noto 字體

NotoSansCJKsc-Regular.otf

特點(diǎn):

  • 覆蓋幾乎全部 Unicode 中文字符
  • 支持 CJK 擴(kuò)展區(qū)
  • 免費(fèi)可商用(SIL OFL)
  • iText / Flying Saucer 完全支持

五、常見字體后綴解析(避免踩坑)

后綴

含義

是否可用于 Java PDF

.ttf

TrueType Font

?

.otf

OpenType Font

?(推薦)

.ttc

字體集合

??(易出問題)

.vf.ttf

可變字體

?(不支持)

.woff / woff2

Web 字體

?

特別警告:Variable Font(VF)

NotoSansCJKsc-VF.ttf

iText / Flying Saucer 完全不支持,使用后常見現(xiàn)象是:

  • 只有數(shù)字、符號
  • 中文正文全部消失
  • 不報錯,非常迷惑

六、Java 端正確的字體加載方式

1. 必須使用IDENTITY_H

BaseFont.IDENTITY_H

作用:

告訴 PDF 使用 Unicode 編碼,而不是單字節(jié)編碼。

2. 強(qiáng)烈建議使用EMBEDDED

BaseFont.EMBEDDED

為什么?

  • NOT_EMBEDDED 只是“引用字體名”
  • 是否能顯示,完全依賴打開 PDF 的環(huán)境
  • 換機(jī)器 / Linux / Docker 必定翻車

你現(xiàn)在能顯示,只是環(huán)境“碰巧”有該字體

3. 標(biāo)準(zhǔn)代碼示例

ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(
    "NotoSansCJKsc-Regular.otf",
    BaseFont.IDENTITY_H,
    BaseFont.EMBEDDED
);

七、最容易被忽略的一點(diǎn):HTML / CSS 才是真正的“使用字體”

1. 一個常見誤區(qū)

“我在 Java 里 addFont 了,為什么中文還不顯示?”

原因是:

addFont 只是“注冊”,不是“使用”

2. 必須在模板中顯式指定font-family

<style>
body {
    font-family: "Noto Sans CJK SC";
    font-size: 12pt;
}
</style>

關(guān)鍵點(diǎn):

  • 使用 字體內(nèi)部 family 名稱
  • 不是文件名
  • 建議寫在 body,讓所有元素繼承

如果不寫這一步,F(xiàn)lying Saucer 會退回到內(nèi)置 Latin 字體,中文直接丟失。

八、為什么換成 Noto 后,版式可能發(fā)生變化?

這是一個正常且不可避免的現(xiàn)象。

原因:

  • 不同字體的字寬不同
  • 行高(ascent / descent)不同
  • 筆畫粗細(xì)不同

因此可能導(dǎo)致:

  • 換行點(diǎn)變化
  • 表格溢出
  • 分頁變化

九、工程級應(yīng)對方案(必須知道)

1. 固定行高

body {
    line-height: 1.4;
}

2. 表格列寬避免“卡死”

優(yōu)先:

width: 25%;

避免:

width: 80px;

3. 字號微調(diào)

經(jīng)驗(yàn)值:

原宋體字號

Noto 建議

12pt

11pt

10.5pt

10pt

十、生僻字驗(yàn)證(上線前必做)

在模板中加入測試文本:

龘 麤 鱻 ?? ??

全部可見,才算真正支持生僻字。

十一、最終推薦的“標(biāo)準(zhǔn)方案”

生產(chǎn)級、穩(wěn)定、可遷移的最佳實(shí)踐

  • 字體:NotoSansCJKsc-Regular.otf
  • 編碼:IDENTITY_H
  • 嵌入:EMBEDDED
  • CSS:body 全局 font-family
  • 行高:顯式設(shè)置
  • 表格:避免極限寬度

十二、一句話總結(jié)

Java 生成 PDF 的生僻字問題,從來不是“渲染問題”,

而是“字體工程問題”。

理解了 字體覆蓋范圍 + PDF 字體嵌入機(jī)制 + CSS 使用方式

這個問題可以一次性、永久性解決。

到此這篇關(guān)于Java生成PDF時該如何正確支持中文生僻字的文章就介紹到這了,更多相關(guān)Java生成PDF支持中文生僻字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中的ForkJoinPool使用方法詳解(附案例)

    Java中的ForkJoinPool使用方法詳解(附案例)

    ForkJoinPool是Java并發(fā)包中的一個重要組件,它是一種特殊類型的線程池,用于支持分而治之的任務(wù)并行執(zhí)行,這篇文章主要介紹了Java中ForkJoinPool使用方法的相關(guān)資料,需要的朋友可以參考下
    2025-09-09
  • Java8深入學(xué)習(xí)系列(三)你可能忽略了的新特性

    Java8深入學(xué)習(xí)系列(三)你可能忽略了的新特性

    一提到Java 8就只能聽到lambda,但這不過是其中的一個而已,Java 8還有許多新的特性,有一些功能強(qiáng)大的新類或者新的用法,還有一些功能則是早就應(yīng)該加到Java里了,所以下面這篇文章主要給大家介紹了關(guān)于Java8中大家可能忽略了的一些新特性,需要的朋友可以參考下。
    2017-08-08
  • java語言自行實(shí)現(xiàn)ULID過程底層原理詳解

    java語言自行實(shí)現(xiàn)ULID過程底層原理詳解

    這篇文章主要為大家介紹了java語言自行實(shí)現(xiàn)ULID過程底層原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • OpenJDK源碼解析之System.out.println詳解

    OpenJDK源碼解析之System.out.println詳解

    這篇文章主要介紹了OpenJDK源碼解析之System.out.println詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • java使用httpclient 發(fā)送請求的示例

    java使用httpclient 發(fā)送請求的示例

    HttpClient 是Apache Jakarta Common 下的子項(xiàng)目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議,這篇文章主要介紹了java使用httpclient 發(fā)送請求的示例,需要的朋友可以參考下
    2023-10-10
  • Java通用工程模塊bom包管理詳細(xì)代碼示例

    Java通用工程模塊bom包管理詳細(xì)代碼示例

    BOM本質(zhì)上是一個普通的POM文件,區(qū)別是對于使用方而言,生效的只有這一個部分,這篇文章主要介紹了Java通用工程模塊bom包管理的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-06-06
  • java創(chuàng)建一個類實(shí)現(xiàn)讀取一個文件中的每一行顯示出來

    java創(chuàng)建一個類實(shí)現(xiàn)讀取一個文件中的每一行顯示出來

    下面小編就為大家?guī)硪黄猨ava創(chuàng)建一個類實(shí)現(xiàn)讀取一個文件中的每一行顯示出來的實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Java中的MapStruct知識點(diǎn)總結(jié)

    Java中的MapStruct知識點(diǎn)總結(jié)

    這篇文章主要介紹了Java中的MapStruct知識點(diǎn)總結(jié),MapStruct是一個Java注解處理器,用于生成類型安全的映射代碼,它可以自動處理源對象和目標(biāo)對象之間的映射,減少了手動編寫重復(fù)的映射代碼的工作量,需要的朋友可以參考下
    2023-10-10
  • Java中的Stream流與IO流完整實(shí)戰(zhàn)指南(從零掌握)

    Java中的Stream流與IO流完整實(shí)戰(zhàn)指南(從零掌握)

    本文詳細(xì)介紹了Java中的Stream流和IO流的使用方法,包括它們的基本概念、核心API、適用場景以及如何正確關(guān)閉資源,通過多個實(shí)戰(zhàn)案例,幫助讀者掌握這些核心技能,提高Java開發(fā)效率,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • Mybatis 中 Oracle 的拼接模糊查詢及用法詳解

    Mybatis 中 Oracle 的拼接模糊查詢及用法詳解

    這篇文章主要介紹了Mybatis 中 Oracle 的拼接模糊查詢及用法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08

最新評論

温州市| 会昌县| 吉林省| 鸡东县| 阿鲁科尔沁旗| 大悟县| 昭平县| 庄河市| 田东县| 鄂托克旗| 九龙坡区| 勃利县| 綦江县| 行唐县| 祁阳县| 莎车县| 新民市| 伊宁县| 唐海县| 道孚县| 蚌埠市| 荆州市| 略阳县| 新建县| 巴马| 贺州市| 楚雄市| 文水县| 洛宁县| 伊川县| 威远县| 喀喇沁旗| 阳东县| 东阳市| 嘉鱼县| 乡城县| 礼泉县| 吴桥县| 绥化市| 巴里| 古浪县|