ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LaTeX中文排版fontspec报错全解析:从编译引擎到字体配置一次搞定

LaTeX中文排版fontspec报错全解析:从编译引擎到字体配置一次搞定 LaTeX写中文文档十个新手九个都在Package fontspec Error这个报错上卡过。明明代码照着模板抄的ctex也导入了结果一点编译红字刷屏英文正常、中文全是乱码甚至直接中止编译。这个错误表面上看是fontspec宏包的问题实际上一头连着LaTeX编译引擎的选择另一头连着系统字体管理和中文排版底层机制要一次性讲透得从报错机制本身说起。我写这篇文章的出发点很简单把我在Windows、macOS、Linux三套环境里处理fontspec报错的经验整理成一套可以直接照做的排查清单从现象到原理从临时解决方案到一劳永逸的配置模板全部覆盖。正打算把VSCode、TeXstudio、TeXworks甚至命令行编译都踩过一遍雷的人这篇就是给你准备的。1. fontspec错误到底是什么先搞清楚报错逻辑1.1 一个典型的报错现场最常见的中文配置脚本长这样\documentclass{article} \usepackage{fontspec} \setmainfont{SimSun} \begin{document} 你好世界。 \end{document}在TeXstudio里点编译结果不是预期中的PDF而是满屏的红色错误信息。核心报错一般是Package fontspec Error: The font SimSun cannot be found.或者更早期的版本会给出! Font \zfbasefontSimSun not loadable: Metric (TFM) file not found.这两种报错都指向同一件事LaTeX找不到你要用的那个中文字体。但为什么找不到原因其实五花八门。先说我总结的几个高频原因排序编译引擎不是XeLaTeX或LuaLaTeX而是默认的pdfLaTeX系统里确实没有安装目标字体字体装了但字体名称写错了用了正确的引擎但fontspec宏包版本过老Windows、macOS、Linux各自字体调用名称不一样1.2 为什么fontspec会在中文配置中炸掉要理解fontspec报错得先理解LaTeX的编译引擎分工。传统pdfLaTeX主要面向西文排版它支持的字体标准是TFMTeX Font Metric Type1字体对系统内安装的TrueType和OpenType字体几乎没法直接使用。中文字体大多数是TrueType或OpenType格式所以用pdfLaTeX编译带中文的文档输出一堆乱码或者直接报缺字体是意料之中的事。XeLaTeX和LuaLaTeX则通过fontspec宏包把系统字体纳入TeX的字体管理范围。fontspec的核心工作说白了就是帮你把系统里以名称存在的字体和TeX内部以字体ID存在的字体做一个映射。而Package fontspec Error说白了就是映射过程中断了要么是映射前道路不通引擎不对要么是映射时找不到对应字体字体名错、字体缺失要么是被映射对象访问受限权限、路径、格式不支持。fontspec报错在中文配置里特别突出还有一个原因中文字体文件名和字体族名称不一致。比如Windows系统里宋体的文件是simsun.ttc但字体族名称是宋体在fontspec里调用时用的是后者。很多人从网上抄来一段\setmainfont{SimSun}在英文Windows上编译没问题换到中文Windows上反而报错就是因为系统字体族名称可能随系统语言环境变化。再看一个更隐蔽的情形很多人把文档写成UTF-8编码用\usepackage[UTF8]{ctex}在pdfLaTeX下编译老版本ctex宏包可以通过CJK机制跑通中文。但一旦某天你把\usepackage{fontspec}也加进去fontspec本身在pdfLaTeX下根本没有实现必然报错。这属于引擎兼容性层面的问题不是字体问题。所以修复fontspec错误思路要分三条线走查引擎、查字体、查宏包配置。下面一节一节来。2. 修复方案一把编译引擎切换到XeLaTeX或LuaLaTeX2.1 为什么必须用XeLaTeX/LuaLaTeX而不是pdfLaTeX很多人百思不得其解同一个.tex文件为什么在别人的电脑上就正常我的就报错别人往往用的是XeLaTeX编译而你的编译按钮默认还是pdfLaTeX。fontspec宏包文档里写得明明白白它只在XeTeX和LuaTeX引擎下才能正常工作。如果你用pdfLaTeX编译fontspec会直接告诉你这个宏包需要XeLaTeX或LuaLaTeX引擎。从设计原理上讲pdfLaTeX处理中文需要依赖CJK方案早期是CJKutf8宏包现在是ctex宏包内部的CJK模式。而XeLaTeX天然支持Unicode可以直接用系统字体渲染中文fontspec就是XeLaTeX下的字体管理接口。所以修复中文配置的第一步不是改任何宏包而是确认自己用对了编译引擎。实际操作中我最推荐的组合是XeLaTeX ctex宏包 fontspec可选LuaLaTeX ctex宏包适合需要Lua脚本做复杂排版的场景绝大多数人直接用XeLaTeX就足够了。LuaLaTeX虽然也支持fontspec但中文排版生态里ctex的兼容性和文档完善度XeLaTeX路径最省心。2.2 在TeXstudio、TeXworks中切换编译引擎TeXstudio默认调用的是pdfLaTeX需要在菜单里设置。操作路径选项-设置-构建-默认编译器把pdfLaTeX改成XeLaTeX。改完以后重新编译你会发现原来报fontspec错误的位置错误消失了。TeXworks更直接编译按钮旁边有一个下拉框默认是pdfLaTeX直接切换成XeLaTeX。如果下拉框里看不到XeLaTeX选项去配置里添加命令xelatex.exe -interactionnonstopmode %.tex。这里必须强调一句网上很多教程会同时让你改两个地方一是默认编译器二是LaTeX命令的完整参数。其实核心就是把编译进程从pdflatex换成xelatex其余参数照旧。还有一种情况如果你在用Overleaf之类的在线编辑器左下角菜单里把编译器从pdfLaTeX切换到XeLaTeX即可字体上传后也一样工作。2.3 在VSCode中配置LaTeX Workshop的引擎与预览VSCode这块我单独拎出来说因为它是当前写LaTeX最主流的编辑器配置方式也最容易踩坑。LaTeX Workshop插件默认会用latexmk调度编译。latexmk本身不会自动判断中文文档必须要用XeLaTeX它默认调用pdfLaTeX。所以你在VSCode里写中文文档报了fontspec错误优先去看settings.json里怎么配置的。我的配置方法只要在settings.json里加两段{ latex-workshop.latex.recipes: [ { name: xelatex, tools: [xelatex] }, { name: latexmk (xelatex), tools: [latexmk] } ], latex-workshop.latex.tools: [ { name: xelatex, command: xelatex, args: [ -synctex1, -interactionnonstopmode, -file-line-error, %DOC% ] }, { name: latexmk, command: latexmk, args: [ -xelatex, -synctex1, -interactionnonstopmode, -file-line-error, %DOC% ] } ] }配置完按CtrlAltB编译或者点开TeX侧边栏的Build按钮选择Recipe为xelatex。实测下来用latexmk -xelatex最稳因为它会自动处理增量编译和辅助文件清理。注意改完settings.json后一定要重启VSCode或者执行Reload Window否则插件不会加载新配置。如果是手滑把%DOC%写成了绝对路径带空格的情况也会间接引发各种不可名状的错误因为Windows命令行对路径空格处理敏感%DOC%用引号包起来最保险。3. 修复方案二让字体真正可用3.1 中文配置里到底是哪些字体在报错引擎切换正确后fontspec可能还是会报错。这时候的问题基本就聚焦在字体找不到上。fontspec默认调用的中文字体是三件套SimSun宋体、SimHei黑体、KaiTi楷体。如果你在Windows上写文档这些字体是系统自带的一般不会报缺字体的错误。但如果你在macOS上系统默认没有SimSun只有宋体-简、华文宋体这类名称自然就找不到。Linux更不用说了默认一个中文字体都没有需要自己安装。为了解决这个问题你需要先搞清楚系统里到底有哪些可用中文字体以及它们的准确名称。Windows上打开C:\Windows\Fonts看字体文件名然后用右键查看详细信息里的字体名称。但更靠谱的做法是用命令行工具查询。在Windows PowerShell里执行Get-Command fc-list或者直接去网上找一个fc-list.exe通常随MiKTeX/TeX Live附带。查字体列表的命令是fc-list :langzh输出会列出所有支持中文的字体格式是C:\Windows\Fonts\msyh.ttc: 微软雅黑:styleRegular注意双冒号后面那个名称才是fontspec里用的名字。比如你想调用微软雅黑应该写\setmainfont{微软雅黑}或者用英文名称Microsoft YaHei。中英文名称在fontspec里大多支持但稳妥起见用英文名称更保险因为中文名称在命令行编码格式不同的环境下容易出错。macOS上查询方法类似终端执行fc-list :langzh但macOS默认没有fc-list需要先安装fontconfig。如果不想装额外工具直接打开字体册应用选中一个字体按CmdI看PostScript名称那个就是fontspec要用的名字。Linux这块最直接的是fc-list :langzh没输出就说明一个中文字体都没装需要先安装。3.2 用fontspec显式指定中文字体查清楚字体名称后在文档里显式指定\documentclass{article} \usepackage{fontspec} \setmainfont{Microsoft YaHei} \begin{document} 你好世界。 \end{document}如果你只想改中文字体不改变西文字体那要用\setCJKmainfont前提是导入了xeCJK宏包\documentclass{article} \usepackage{xeCJK} \setCJKmainfont{Microsoft YaHei} \setCJKsansfont{SimHei} \setCJKmonofont{KaiTi} \begin{document} 中文测试 123abc \end{document}xeCJK是专门负责中日韩文字排版的宏包fontspec处理西文xeCJK处理CJK两者配合使用是中文LaTeX的经典组合。这里有一个很多人都忽略的细节fontspec和xeCJK对字体名称的处理不区分中英文别名但是对字体文件格式有要求。SimSun对应的字体文件是simsun.ttc一个TTC文件里包含多个字体。fontspec能正常读取TTC但如果你手动指定了字体文件路径而非名称写法是这样的\setCJKmainfont[Path./fonts/]{SimSun}这个Path参数表示字体文件位于当前目录下的fonts子目录里。这个方法适合把自定义字体随文档一起分发确保换台电脑也能编译。3.3 Windows、Mac、Linux三套环境下字体名称的具体差异实操中我发现很多人报fontspec错误不是缺字体而是字体名写错。因为字体在不同系统里叫法不一样而且中英文还各有一套别名。整理成表格如下系统宋体字体族名黑体字体族名推荐调用名Windows宋体黑体SimSun, SimHeiWindows微软雅黑Microsoft YaHeiMicrosoft YaHeimacOS宋体-简黑体-简Songti SC, Heiti SCmacOS华文宋体华文黑体STSong, STHeitiLinuxAR PL UMingAR PL UKaiAR PL UMing CN, AR PL UKai TW写fontspec配置时至少要准备两套方案一套是Windows下的SimSun/SimHei一套是macOS下的Songti SC/Heiti SC。最省事的做法是在宏包加载前用条件判断\usepackage{ifplatform}不过这个宏包在Linux下需要额外的shell escape支持稍微麻烦。更轻量的方案是直接用ctex宏包的fontset选项自动判断\documentclass[fontsetwindows]{article}fontset可以填windows、mac、ubuntu、fandol等它会自动匹配对应系统的字体。fandol是TeX Live自带的开源中文字体集即使系统里没有任何中文字体用fontsetfandol也能编译通过。这是我在Linux服务器上最常用的方案。4. 修复方案三用ctex宏包一劳永逸4.1 ctex宏包/文类的工作原理前面说的都是手动管字体有点繁琐。对大多数论文、报告、作业来说直接上ctex宏包是效率最高的方案。ctex宏包做了什么事情它封装了fontspec、xeCJK、setspace等一堆宏包自动处理中文字体配置、段落缩进、标题格式、行距等细节。你不需要自己写\setCJKmainfont它直接按系统自动选择默认字体。我先说一个关键选择ctex宏包和ctexart文档类二选一就行不要同时混用。推荐用文档类\documentclass[UTF8]{ctexart} \begin{document} 你好世界。 \end{document}编译方式选择XeLaTeX。这种方式下\section{}标题自动变成中文的一、二、三编号摘要、目录、参考文献相关的本地化设置也都帮你处理好了。ctex默认的fontset跟随系统自动判定Windows上就自动用SimSunmacOS上自动用Songti SCLinux上默认尝试用系统安装的中文字体找不到就退回fandol。这个自动判断在99%的场景下都够用遇到判断不准确时手动指定\documentclass[UTF8, fontsetfandol]{ctexart}强制使用fandol字体集不管系统装没装中文字体都能编译。但字体观感上相对普通只适合应急。4.2 一套经过大量验证的中文模板我自己保存了一套模板写中文文档基本就是从它改起。这里分享出来你可以直接拿去当起点\documentclass[UTF8, zihao-4, fontsetwindows]{ctexart} \usepackage{amsmath, amssymb} \usepackage{graphicx} \usepackage{booktabs} \usepackage{geometry} \geometry{a4paper, margin2.5cm} \title{基于某方法的研究} \author{你的名字} \date{\today} \begin{document} \maketitle \begin{abstract} 这里是摘要内容。 \end{abstract} \section{引言} 这里是正文。 \end{document}几点说明zihao-4表示小四号字这是国内论文通用字号。fontsetwindows在Windows上编译最稳如果你要在macOS和Linux之间切换把这一行改成fontsetmac或fontsetfandol或者干脆删掉让ctex自动检测。加了ctexart后不要再手动加载xeCJK和fontspec否则可能产生宏包选项冲突。如果你确实需要额外字体命令再显式加载但一般用不到。在我实际测试中这套模板在TeX Live和MiKTeX上都能直接通过XeLaTeX编译报错率极低。我对工作室的学生要求是先拿这个模板跑通再往上加内容遇到编译问题先怀疑自己新加的部分而不是怀疑ctex基础配置。5. 排查思路与报错速查从日志到一键定位5.1 错误日志怎么看用XeLaTeX编译时.log文件里记录了所有关键信息。遇到Package fontspec Error不要重新编译一遍再猜直接打开.log文件搜fontspec关键词能看到类似这样的段落Package fontspec Warning: Font SimSun not found. Package fontspec Info: Could not resolve font SimSun (using fallback).这段信息明确告诉你是字体没找到。如果日志里出现的是Package fontspec Error: The font SimSun cannot be found.多半是字体名称问题或者是fontset检测错误。这时候检查两点一是系统是否真的装了该字体二是字体文件是否完整可用。还有一类错误是在你用了\setmainfont{...}时传参多了[]导致语法错误比如\setmainfont{SimSun}[LigaturesTeX]这句话语法其实是合法的但如果你把参数顺序写反了就会变成\setmainfont[LigaturesTeX]{SimSun}这种情况fontspec也能识别老版本会警告新版本直接报错。所以写配置时字体名写在花括号里选项写在方括号里顺序不能反。5.2 常见报错速查表我把遇到的典型fontspec相关报错整理成一张表方便对号入座报错关键字典型原因解决方法The font XXX cannot be found字体不存在或名称错误用fc-list查准确名称改用已安装字体The fontspec package requires XeTeX编译引擎用了pdfLaTeX切换编译器为XeLaTeX或LuaLaTeXInvalid fontname字体名称包含特殊字符给字体名加引号或用文件路径方式调用Font XXX not loadable: Metric (TFM) file not found旧引擎尝试加载Type1字体失败确认引擎是XeLaTeXxeCJK Error:CJKfont XXX undefined中文字体未正确定义用\setCJKmainfont重新指定ctex error: fontset windows is not availableTeX发行版缺少对应字体集改fontsetfandol或安装对应字体这里要单独提一个坑ctex在Linux下报fontset windows is not available并不代表你系统里没有SimSun而是ctex宏包在编译时判定当前平台不是Windows就拒绝使用windows字体集。解决办法很简单加[fontsetfandol]或者主动给系统装中文字体并让ctex自动检测。5.3 从实际操作中总结的六个避坑细节写LaTeX中文配置这几年我在fontspec上栽了不少跟头有些坑网上很少有人提这里一并写出来。第一TTC字体文件的名称解析问题。simsun.ttc是TTC集合里面同时包含宋体和某些扩展字体。fontspec在部分老版本中对TTC内的字体子集名称解析存在bug会报找不到字体。新版本TeX Live 2023之后修复得比较好如果你还在用TeX Live 2019或者更早版本中文配置出问题先升级发行版。第二环境变量和PATH导致找不到XeLaTeX。Windows下如果装了多个TeX发行版比如MiKTeX和TeX Live共存命令行执行xelatex可能调用的是旧版而VSCode插件调用的是新版两边字体缓存不一致就会出现同样的文档在命令行编译通过、在VSCode里报错的情况。我的建议是只装一个TeX发行版或者把不需要的那个从PATH里去掉。第三字体缓存文件损坏。XeLaTeX依赖fontconfig的字体缓存Windows和Linux下都有这个机制。有时候你明明刚安装了新字体但fc-list里看不到或者fontspec还是报缺字体多半是缓存没刷新。Linux下执行fc-cache -fWindows下把C:\Users\用户名\AppData\Local\Fontconfig目录删掉后重启程序即可。第四用了\usepackage{fontspec}但没写\setmainfont。这么说可能有点反直觉但有时候fontspec报错不是因为它出错而是因为你没告诉它用哪个字体。fontspec在默认情况下会使用LaTeX默认字体Latin Modern不指定中文字体时正文里的中文会变成空白方块。这不算硬性报错但效果上跟报错差不多。用ctex宏包可以规避这个问题。第五全角标点和空格问题。这个不是fontspec直接报错但经常和fontspec问题一起出现。用XeLaTeX编译时全角逗号、句号、引号都可能因为字体不支持而显示成方框。比如某些英文字体里没有全角逗号\setmainfont只设置了西文字体xeCJK又没设置\setCJKmainfont中文标点就会掉进西文字体渲染通道。解决方法是确保\setCJKmainfont指向一个支持中文标点的字体。第六禁用自动\setmainfont带来的副作用。ctex宏包在fontsetwindows下会自动调用\setCJKmainfont{SimSun}有些人为了用一个特殊中文字体手动覆盖了\setCJKmainfont结果西文和中文之间的间距异常字重配比失调。这时的正确做法是同时配置好中文和西文字体保持整体观感统一不要只管中文字体。6. 进阶建议如何让XeLaTeX和fontspec的中文排版更好看6.1 字重与字形扩展默认\setCJKmainfont只指定Regular字重但中文字体通常有Light、Regular、Medium、Bold等字重。如果你在文档里用\textbf{}加粗中文而你没有给BoldFont指定字体xeCJK会做伪加粗效果差强人意。更好的配置是这样\setCJKmainfont[AutoFakeBoldfalse, BoldFontSource Han Sans SC Bold]{Source Han Sans SC}这里的AutoFakeBold是xeCJK的一个选项默认开启时用算法加粗关闭后要求你手动指定BoldFont。我一般建议关闭自动伪加粗手动指定真粗体因为算法加粗在某些PDF阅读器上边缘发虚打印出来尤其明显。前提是你安装了对应的粗体字体。6.2 标点压缩与中文排版细节LaTeX中文排版比英文多一个很重要的需求标点压缩。中文引号、逗号、句号在行首行尾的避头避尾规则ctex宏包默认已经处理了。如果你自己用xeCJK裸配需要额外开启\xeCJKsetup{CJKecglue{\hspace{0.2em}}}来控制中西文之间的间距。这里有个判断标准如果你的文档是正式论文直接用ctexart如果是做幻灯片用ctexbeamer或直接用Beamer加\usepackage{ctex}如果只是写几行中文测试用ctexart最省事。6.3 一个值得尝试的轻量方案如果你不想装字体也不想折腾字体名还有一个轻量方案使用Noto Sans CJK和Source Han Sans。这两套字体的开源版本通常包含在TeX Live的fandol字体集中安装后fontsetfandol也能获得不错的中文排版效果。Linux用户尤其推荐因为fc-list :langzh能明确看到这两个字体的PostScript名称Noto Sans CJK SC Noto Serif CJK SC Source Han Sans SC Source Han Serif SC在配置里写\setCJKmainfont{Noto Serif CJK SC} \setCJKsansfont{Noto Sans CJK SC}这对组合在屏幕和打印上都有不错的表现而且跨平台一致性好。7. 写在最后的经验教训Package fontspec Error这个报错本质上不是宏包本身出了什么大问题而是你的文档环境、字体资源、编译引擎三者没有对齐。我处理过无数个这样的问题案例总结下来修复路径其实就三步确认用XeLaTeX编译、确认字体名称正确、确认排版宏包ctex或xeCJK配置合理。三步走完99%的报错都能消失。剩下那1%里最让人抓狂的是某个字体文件本身损坏或者编码不标准例如从网上下载的所谓仿宋_GB2312实际是个坏字体。遇到这种直接换开源字体库里的字体替换几分钟就能解决。我对初学者的建议是第一天接触LaTeX中文配置不要同时装一堆宏包也不要一上来就在ctex和xeCJK之间左右横跳固定一套组合用熟。我推荐就从ctexart加XeLaTeX开始等跑通了再研究fontspec底层细节不迟。这套路径我验证过太多遍是真的省心。
返回列表