CJK+GBK中文字体生成器:让LaTeX老项目重获新生的实用指南

发布时间:2026/9/9 9:25:43
CJK+GBK中文字体生成器:让LaTeX老项目重获新生的实用指南 简介面向LaTeX排版用户这份资源专为解决CJK宏包缺少GBK中文字体、中文无法正确显示的问题而设计。资源包内含字体生成及转换工具能够搭配Texlive环境生成GBK编码的宋体、黑体、仿宋、楷书等字体适合撰写学术论文或日常中文文档的用户。压缩包共10个文件主要包括可直接运行的exe工具、用于编译制作的makefile与bat脚本、C语言源码以及配置文件整体仅289KB轻量实用。使用后可省去手动寻找字体的麻烦只需按说明将生成文件放入系统字体目录再在LaTeX文档中调用CJK宏包即可正常显示中文。已有1469人学习下载。对需要在中英文混排或GBK编码文档中获得稳定字体的Texlive用户来说这套工具能显著降低配置成本提升中文排版效率。 很多年不用LaTeX写中文文档的人可能觉得我在炒冷饭——都什么年代了XeLaTeX配ctex宏包一套搞定的东西为什么还要提CJKGBK这套老掉牙的组合但我前阵子帮人处理一个老旧的论文模板时真真切切地被教做人了。模板是十几年前流传下来的依赖dvipdfmx驱动里面的tex源文件全部是GBK编码注释里还有大量依赖CJK宏包的旧命令。如果不用CJK就得把整个模板用GBK转UTF-8重写一遍还得手工调整参考文献格式、页眉页脚、浮动体位置。折腾半天下来我意识到CJKGBK这套方案并没有完全退出历史舞台它依然是很多历史项目、毕业设计模板和期刊投稿模板的底层依赖。而让这套老方案重新跑起来的关键就是CJKGBK中文字体生成器。这个东西的作用是把系统里的中文字体比如宋体、黑体、仿宋、楷体转换成CJK宏包能识别的字体文件并生成对应的字体映射、字体描述和虚拟字体文件。加上GBK编码的中文字体文件一并放到Texlive的目录树里刷新字体缓存之后旧模板就能正常编译了。这篇文章我就把这个过程从头到尾拆一遍把原理和实操结合起来讲给还在用或者不得不继续用CJK方案的朋友一份能直接照着做的指南。1. 为什么还需要CJKGBK这套老方案1.1 从我的实际遭遇说起事情是这样的。朋友发来一个压缩包打开一看里面全是.tex、.bib、.bst文件还有一个main.tex入口。我当时的机器上装的是完整版Texlive 2024一开始我直接用xelatex去编译报错刷了一屏又一屏。仔细一看模板代码里写的都是\usepackage{CJK}、\begin{CJK*}{GBK}{song}这类已经很少见的东西。如果只是几个文件手动改也就改了。但那是一个几十章的学位论文模板每个章节文件里都有大量中文内容。更麻烦的是模板里的\bibliographystyle、图表引用格式、目录样式全跟CJK宏包耦合在一起硬切成ctex方案要动的地方太多风险极大。最稳妥的办法就是把CJK宏包的运行环境重新搭起来。1.2 CJK宏包的运行机制与GBK定位简单解释一下CJK宏包的工作原理。它在LaTeX层面处理中文的方式是在字符层面上把汉字当作“特殊符号”来处理——每个汉字对应一个“盒子”盒子里放的是某个字体文件中定义的字形。编译时CJK宏包会根据指定的编码方案把源文件里的中文字符映射到对应的字体槽位。这里说的编码方案包括GBK、UTF8、Bg5、GB等。重点在于源文件用什么编码宏包就按什么编码去解释。如果源文件是GBK编码而你用UTF8模式加载那十个字里面至少有八个变成乱码。所以我那个模板必须使用GBK编码参数并且配套的字体文件也必须能支持GBK字符集的索引。而字体生成器干的活正是把系统中现成的TTF、TTC、OTC字体转换成CJK宏包运行时需要的TFMTeX字体度量、VF虚拟字体、FD字体定义、MAP字体映射文件。没有这些文件LaTeX编译时根本找不到字体更别提把汉字正确排版出来。2. 字体生成器到底干什么活2.1 一次字体生成全流程拆解用大白话说字体生成器做的事情可以分成三步。第一步是解析系统字体。它读取你准备好的中文字体文件比如simsun.ttc、simhei.ttf分析字体内部的字符表、字距信息、字形索引。这一步还会把GBK编码中每个“区位码”对应的字符映射到字体文件里的具体字形ID上。第二步是生成TFM和VF文件。TFM文件记录的是每个字符的宽度、高度、深度等排版度量信息告诉TeX引擎每个汉字该占多大地方。但由于系统字体的字距信息很复杂TFM里无法直接表达全部细节所以就用VF文件作为中间层把TeX层面的字体访问转换成对真实字体的调用同时允许插入额外的字符间距和变形指令。第三步是生成FD和MAP文件。FD文件是字体定义文件告诉CJK宏包“在什么编码方案下、什么字体族名对应的字体文件叫什么”。MAP文件则是给dvipdfmx这类后端驱动用的它建立了字形引用和实际字体文件路径之间的对应关系。编译时dvipdfmx读取MAP文件正确地把PDF里嵌入的中文字体指向你系统里安装的那个TTF或TTC文件。2.2 关键文件类型说明很多新手看到生成的四个文件类型就有点懵这里我按理解难度排序说明一下。FD文件最容易理解。它定义的是宏包级别的映射关系。比如你写\begin{CJK*}{GBK}{song}宏包就去查C70song.fd看这个song字体族在C70编码下具体使用什么外部字体名。TFM文件TeX排版时必须的度量信息文件。没有TFMTeX根本无法确定行宽、对齐、换行所需的所有尺寸数据。VF文件可以当作“把多个字符和一个字符对应起来再附加微调”的包装层。CJK宏包生成的GBK字体一个汉字可能对应多个TFM槽位的组合VF就是用来协调这个对应关系的。MAP文件提供给dvipdfmx的映射表。它告诉PDF生成器“当前这个字体引用对应系统里的哪个真实字体文件我该去哪里载入它并嵌入到PDF里。”理解了这些后面实际操作时就不会抓瞎了。3. 实操从字体文件到能编译的中文文档3.1 准备阶段工具与字体源文件先过一遍需要用到的工具和材料。首先是字体源文件。最简单的方法是直接从Windows系统字体目录取路径一般是C:\Windows\Fonts。我用的这几个是simsun.ttc宋体、simhei.ttf黑体、simkai.ttf楷体、simfang.ttf仿宋。注意simsun.ttc是TTC集合文件里面包含多个字体生成时要指定具体取哪个索引里的字体。然后是字体生成工具。这一套东西我用了开源的cjk-fonts自动构建脚本配合fontforge和otf2tfm来操作字形数据。在Windows下也可以用Texlive自带的cjk-utils包里的工具来手工处理。为了方便演示我在Ubuntu 22.04下操作先安装基础依赖sudo apt update sudo apt install fontforge perl-tk tlmgr install cjk cjk-utils cjk-fonts顺带说明这一步如果你用完整版Texlive 2024其实cjk、cjk-utils已经默认装好了。我装的是basic版所以需要手动补上。3.2 生成字体并刷新树把字体文件放到一个工作目录比如~/cjkfont/work/然后写一个简单的生成脚本。脚本的核心逻辑是遍历目录下所有字体文件调用fontforge将TTF/TTC转为BDF格式再用cjk-fonts的自动化脚本处理BDF生成TFM、VF、FD、MAP文件。实际操作中我直接用了社区维护的cjk-fonts项目它提供了一套写好的Makefile只需要填好字体路径和输出名称执行即可git clone https://github.com/texlive/cjk-fonts.git cd cjk-fonts cp /mnt/windows/Windows/Fonts/simsun.ttc . make songmake song会把宋体相关的所有文件生成到build/song/目录下输出文件包括song.tfm、song.vf、c70song.fd、song.map等。生成完毕把文件安装到本地texmf树mkdir -p ~/texmf/fonts/tfm ~/texmf/fonts/vf ~/texmf/fonts/map/dvipdfmx ~/texmf/tex/latex/CJK cp build/song/*.tfm ~/texmf/fonts/tfm/ cp build/song/*.vf ~/texmf/fonts/vf/ cp build/song/*.map ~/texmf/fonts/map/dvipdfmx/ cp build/song/c70song.fd ~/texmf/tex/latex/CJK/最后一定要刷新字体数据库和文件名数据库否则TeX什么都找不到mktexlsr ~/texmf updmap-sys --enable Mapsong.map注意updmap-sys需要root权限。如果只想对当前用户生效用updmap-user --enable Mapsong.map。3.3 完整测试文档环境搭好之后我写了个最小测试文件来验证效果。注意源文件必须保存为GBK编码不能是UTF-8否则CJK宏包在GBK模式下会报错或输出乱码。\documentclass[12pt]{article} \usepackage{CJK} \begin{document} \begin{CJK*}{GBK}{song} 你好世界。这里测试CJK中文字体。\\ {\bfseries 粗体测试} \\ {\itshape 斜体测试} \\ \end{CJK*} \end{document}用LaTeX编译并生成PDFlatex test.tex dvipdfmx test.dvi如果一切正常生成的PDF里应该正确显示中文字体是宋体风格。字体嵌入这方面dvipdfmx会依据MAP文件自动完成最终PDF文件会内嵌需要的字形。测试时我还顺手做了一个全套测试用不同字体族名替换song分别测试黑体、楷体、仿宋的编译结果确认FD文件、VF文件、字体文件相互配合正常。4. 常见问题与排查技巧实录4.1 gbk/utf-8乱码与UnicodeDecodeError这个问题出现率极高。有一次我生成字体文件后直接用VSCode打开tex源码发现所有中文都变成了一片乱码。原因很简单——VSCode默认用UTF-8打开文件而我的源文件是GBK编码。这不代表文件坏了只是打开方式不对。在VSCode里点击右下角的编码显示比如UTF-8选择“通过编码重新打开”然后在弹出列表里选择“简体中文(GBK)”内容就能正常显示。但还有一个坑如果你用脚本批量修改tex文件脚本里用了Python或Node.js又默认以UTF-8读取文件就会遇到经典的UnicodeDecodeError: gbk codec cant decode byte 0x94 in position 2952。按提示看的话是字节流里包含了GBK无法解析的二进制序列或者反过来文件是GBK编码但你用GBK解码不了某段数据。我的解决办法是统一在Python脚本里显式指定编码读取和写入with open(chapter1.tex, r, encodinggbk, errorsreplace) as f: content f.read()如果源文件编码不确定可以先读二进制再用chardet检测但最稳妥的还是搞清楚文件到底是什么编码再决定如何转换。4.2 字体找不到、地图文件缺失报错编译时报Font not found或Cannot find font song这类错误最常见的两个原因。第一个是字体文件没有安装到正确的位置。确认song.tfm、song.vf是否在~/texmf/fonts/tfm/和~/texmf/fonts/vf/目录下再跑一遍mktexlsr刷新文件名数据库。第二步是确认song.map是否被updmap启用如果MAP文件没启用dvipdfmx就看不到字体引用和实际字体文件的对应关系自然就报找不到字体。第二个原因很隐蔽——字体文件本身是TTC格式但MAP文件里写的是TTF路径。有些自动生成工具在处理TTC时不会自动拆分字体索引导致dvipdfmx加载字体失败。解决办法是在MAP文件里明确指定TTC索引比如song UniGB-UTF16-H SimSun-TTC/UniGB-UTF16-H simsun.ttc或者干脆用工具把TTC拆成单个TTF文件再重新生成。4.3 避坑经验汇总表这里把我踩过的坑汇总成表方便大家快速对照。问题现象可能原因解决方法编译报Cannot find fontFD文件缺失或字体度量文件路径不对重新检查TFM、VF、FD文件位置运行mktexlsrdvipdfmx报Cannot locate font map fileMAP文件未启用用updmap-user --enable Mapxxx.map启用PDF中中文位置错乱、间距异常VF文件缺失或版本不匹配重新生成VF文件确保与TFM配套编译时提示编码不匹配源文件编码与CJK参数不一致统一使用GBK编码保存源文件GBK文件在编辑器中显示乱码编辑器默认UTF-8读取用编辑器的“通过编码重新打开”功能切换GBK字体字形缺失显示方框字体文件不完整或索引错位换用完整版系统字体确保字体文件包含常用汉字4.4 从GBK到UTF-8的批量转换技巧如果你的项目最终要升级到新方案摆脱CJKGBK限制可以考虑做一次编码迁移。这一步最怕的就是转换一半出乱码原文件还没备份。稳妥的做法是先备份整个目录再用Python脚本批量转换编码。import os from pathlib import Path for p in Path(.).rglob(*.tex): data p.read_bytes() try: text data.decode(gbk) except UnicodeDecodeError: print(fskip: {p}) continue p.write_text(text, encodingutf-8) print(fconverted: {p})这个脚本会把所有能按GBK解码的tex文件转为UTF-8。转换完成后再配合ctex宏包做进一步升级就会顺畅很多。注意转换前一定要先确认文件确实是GBK编码否则强行解码会导致不可逆的数据损坏。5. 字体生成与方案选择的个人心得字体生成器这套东西说难也难说简单也简单。难在你要理解LaTeX字体机制——TFM、VF、FD、MAP之间的关系初次接触容易一头雾水。但一旦理解了原理实际操作就是一个固定流程准备好字体源文件、运行生成工具、安装到正确目录、刷新数据库、启用映射、测试编译。整个过程我用熟练之后生成一套字体只要十分钟左右。我自己在这个过程里的最大体会是老方案不一定非要淘汰关键看你的场景需求。如果你的项目已经在CJKGBK体系下稳定运行了很多年模板、样式、参考文献格式都绑定得很深硬换新方案反而容易带来一堆新问题。这时候把字体生成器掌握好让老方案继续平稳运转反而是最经济高效的选择。当然如果是新开项目我仍然建议直接上XeLaTeX ctex UTF-8毕竟编码、字体调用都简单得多踩坑少后续维护也省心。但万一你跟我一样某天被一个积灰多年的CJK项目找上门这篇文章里记录的这套操作流程和排查经验应该能帮你少走不少弯路。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询