1. 问题定位先搞清楚是“编译报错”还是“PDF 不显示”这个话题看起来像是一个小问题实际上它包含两类完全不同的故障一类是编译阶段直接抛出错误导致 PDF 根本生成不出来另一类是编译成功了但 PDF 里的中文要么变成空白要么变成一排问号、方块甚至干脆整段消失。这两类问题的排查路径差别很大混在一起查只会越查越乱所以我一般先做个简单判断看终端里有没有报错信息看输出目录里有没有生成 PDF 文件。如果生成 PDF 了但中文不对说明编码和字体链路里某一环没打通如果连 PDF 都没生成那说明问题在编译参数、宏包加载或者文件编码层面。我在实际排查中遇到最多的组合是编辑器本身保存的文件编码不是 UTF-8同时编译器选择的是传统的pdflatex再加上中文宏包加载顺序不对这三件事叠在一起。单独看每一件都不致命合在一起就是“报错 不显示”的双重症状。先把结论摆出来在 Windows 上使用 VS Code 写中文 LaTeX最稳妥的组合是UTF-8 编码 xelatex编译器 ctex宏包。这套组合能覆盖绝大多数中文排版需求下面所有的排查和配置都围绕它展开。你如果现在就想动手改可以先跳到第三节看配置再回头理解原理如果已经踩坑了建议按第一节的顺序走一遍避免改了半天没改到点上。需要提前说明的是本文提到的所有路径、文件名、配置片段都来自通用实践你在自己机器上要按实际安装位置替换。VS Code 的 LaTeX 插件生态这几年变化不小LaTeX Workshop是主流选择下面的配置也都基于它。如果你用的是别的编辑器或别的插件思路一样但具体字段名会有差异。2. 中文不显示的根因拆解编码、字体、编译链三条线索2.1 文件编码不是 UTF-8中文在源头就烂了这是最隐蔽也最常见的一条。Windows 中文环境下记事本等工具默认可能保存为 GBK 编码VS Code 打开这类文件时如果没识别出来你看到的“正常中文”其实在磁盘上是另一套字节。等你保存、编译PDF 里自然就是乱码或者空白。更麻烦的是有时候 VS Code 打开时显示正常是因为它做了自动猜测但磁盘上其实还是 GBK编译时读的是原始字节编辑器显示和磁盘实际内容不一致这种“看起来没问题”的假象最容易让人走弯路。排查方法很直接看 VS Code 右下角状态栏的编码标识。显示UTF-8才算过关如果显示GBK、GB2312或者UTF-8 with BOM都得处理。带 BOM 的 UTF-8 在某些编译器下会在文件开头插入不可见字符导致首行报错这个坑我在早期项目里踩过不止一次报错信息往往指向第一行的\documentclass看起来莫名其妙。转换方式点击右下角编码 → 选择“通过编码保存” → 选UTF-8。转完之后建议把文件关掉重开一次确认状态栏稳定显示UTF-8。如果你有一批文件要处理可以用脚本批量转换但注意别把已经是 UTF-8 的文件再转一遍容易出 BOM。注意转换编码会改写整个文件操作前先提交一次版本或者备份尤其是那些已经写了几百行的稿子。2.2 编译器选错中文宏包根本没有生效环境传统pdflatex对中文的支持是通过CJK宏包这类方案实现的配置繁琐、字体支持有限遇到稍复杂的中文排版就容易出问题。xelatex从设计上就支持 Unicode 和系统字体配合ctex宏包是现在的主流做法。很多“中文不显示”的案例追到底就是编译器还停留在pdflatex。判断当前用的是哪个编译器看 VS Code 输出面板里LaTeX Workshop打印的编译命令会明确写出pdflatex还是xelatex。如果你没做任何配置插件默认会用latexmk走一遍而latexmk的默认规则往往落到pdflatex上。这就是为什么很多人“什么都没改就是不显示中文”。这里有个容易混淆的点latexmk本身不是编译器它是一个自动化调度工具负责按依赖关系多次调用真正的编译器。所以要改的不是latexmk而是让它调用的引擎变成xelatex。理解这一层配置的时候就不会乱改。2.3 宏包加载顺序和参数不对字体找不到ctex宏包负责中文排版的一系列底层设置包括字体选择、行距、标点处理。它加载时会去系统里找中文字体找不到就报错或者静默降级。常见的错误信息是字体名找不到或者提示某个字体文件缺失。Windows 上一般用SimSun宋体、SimHei黑体、KaiTi楷体这些系统自带字体正常安装的系统都有但也存在被精简版系统裁掉的情况。加载ctex有两种方式用\documentclass[UTF8]{ctexart}这样的文档类或者在标准文档类里\usepackage[UTF8]{ctex}。前者更省事后者更灵活。两种方式都需要保证参数UTF8和实际文件编码一致写错了同样会出问题。我一般推荐直接使用ctexart、ctexbook这类文档类少一层配置就少一个出错点。另一个细节是字体集参数。ctex支持fontsetwindows、fontsetmac、fontsetubuntu等选项Windows 上默认就会走windows一般不用手动指定。但如果你在别人机器上拷来的模板里看到fontsetmac那在 Windows 上必然出问题这时候要么删掉这个参数要么改成windows。3. 从零配置一套能跑中文的环境VS Code LaTeX Workshop 实操3.1 编译链路的选择逻辑为什么是 xelatex 而不是 pdflatex先说清楚取舍。pdflatex的优势是编译速度快、生态成熟、很多老模板只兼容它劣势是对 Unicode 和系统字体支持差中文要用CJK方案配置复杂且排版效果一般。xelatex直接支持 Unicode能调用系统字体中文排版质量明显更好缺点是编译稍慢极少数老宏包不兼容。对于写中文文档这个场景xelatex的优势是压倒性的。我实测过同一份带中文的文档pdflatex下要么报错要么字体丑陋换xelatex后一次通过。所以除非你维护的是必须兼容老引擎的模板否则没有理由不用xelatex。latexmk在这里的角色是“自动挡”它会根据文件里是否引用了参考文献、是否有索引、是否需要多次编译才能稳定的交叉引用自动决定跑几遍。手动敲xelatex两三次也能达到同样效果但容易漏。所以配置思路是让latexmk用xelatex作为底层引擎一次性解决“编译次数”和“引擎选择”两个问题。3.2 settings.json 的关键字段逐项说明VS Code 的 LaTeX Workshop 配置都在settings.json里。打开方式CtrlShiftP→ 输入Open Settings (JSON)。下面这份配置是我目前用的覆盖中文编译和常用辅助功能{ latex-workshop.latex.tools: [ { name: xelatex, command: xelatex, args: [ -synctex1, -interactionnonstopmode, -file-line-error, %DOC% ] }, { name: latexmk-xelatex, command: latexmk, args: [ -synctex1, -interactionnonstopmode, -file-line-error, -xelatex, %DOC% ] } ], latex-workshop.latex.recipes: [ { name: xelatex, tools: [xelatex] }, { name: latexmk (xelatex), tools: [latexmk-xelatex] } ], latex-workshop.latex.recipe.default: first }逐个字段解释。tools定义可用的编译工具每个工具是一条完整命令。-synctex1生成同步文件支持 PDF 和源码之间双向跳转写长文档时非常有用。-interactionnonstopmode让编译遇到错误不中断等待输入否则在编辑器里会卡住。-file-line-error让报错信息带上文件名和行号排错效率提升明显强烈建议保留。%DOC%是占位符会被替换成当前主文件名不含扩展名。注意是主文件如果你的项目有多个.tex文件要在主文件上执行编译。recipes定义编译配方一个配方可以串多个工具按顺序执行。这里给了两个配方单次xelatex和latexmk驱动xelatex。日常用后者更省心它会自动处理交叉引用需要的多轮编译。recipe.default设成first表示默认用第一个配方。如果你想默认走latexmk把配方顺序调换或者把值改成配方名。我个人的习惯是日常用latexmk (xelatex)因为文档里一旦有目录、参考文献、交叉引用单次编译的结果是不稳定的需要多轮才能收敛。还有一个常被忽略的点latex-workshop.latex.outDir。默认输出在源文件同目录会生成一堆.aux、.log、.synctex.gz文件把目录搞得很乱。可以设成%DIR%/build集中管理但要注意主文件的相对路径引用比如插图路径可能需要相应调整这一点后面会细说。3.3 一份最小可运行的中文模板配置改完用下面这份最小模板验证环境是否打通\documentclass[UTF8, a4paper, 12pt]{ctexart} \usepackage{geometry} \geometry{left2.5cm, right2.5cm, top2.5cm, bottom2.5cm} \usepackage{graphicx} \usepackage{amsmath} \title{中文排版测试文档} \author{测试} \date{\today} \begin{document} \maketitle \section{中文标题测试} 这是一段中文正文用来验证字体是否正常加载、标点是否正常显示。 公式测试$E mc^2$。 \end{document}几个关键点。\documentclass的UTF8参数要和文件实际编码一致。ctexart自带中文支持不需要再额外加载ctex。a4paper和字号放在文档类选项里比后面用宏包调更规范。中文段落里混排英文和公式是常态ctex会自动处理中西文间距不用手动加空格。编译后如果 PDF 里中文正常说明链路通到底了。如果标题、正文都正常但某一处异常比如数学公式里的中文、表格里的中文、图表标题里的中文那就是局部问题排查范围可以大幅缩小。4. 常见报错逐条拆解与现场处置4.1 字体找不到从报错信息反推缺什么典型报错长这样Font SimSun not found或者The font ... cannot be found。出现这类信息说明xelatex在系统字体目录里没找到指定字体。先确认报错里点名的是哪个字体然后去系统字体设置里找。处置思路分三层。第一层确认字体是否真的存在。打开系统字体目录搜一下报错里的名字。第二层如果字体存在但xelatex找不到可能是字体缓存问题重装或刷新字体缓存后再试。第三层如果字体确实缺失精简系统常见要么从别处拷一份字体文件装进来要么改用系统里已有的字体在文档类选项里显式指定。显式指定字体的写法\documentclass[UTF8, fontsetwindows]{ctexart}如果windows字体集里某个字体缺失可以单独覆盖\setCJKmainfont{SimSun}但要注意单独覆盖只影响主字体标题、无衬线等字体可能还是走默认报错可能依然存在。所以最稳的做法是补齐系统字体而不是逐个覆盖。注意字体名区分大小写和写法SimSun和simsun在不同环境下表现可能不同尽量按系统里显示的准确名称写。4.2 编译卡住不结束nonstopmode 的必要性不带-interactionnonstopmode时编译遇到错误会停下来等用户输入在 VS Code 这种非交互环境里表现为“一直转圈”。很多人以为是编辑器卡了其实是编译器在等一个永远不会到来的按键。加上这个参数后编译遇到错误会继续往下跑把所有错误一次性打印出来排查效率高得多。这个参数也有副作用它会让编译“带病运行”即使有错误也可能生成一个残缺的 PDF。所以看到 PDF 生成了不要高兴太早一定要检查输出面板里有没有错误。我一般把“编译成功”定义得更严格输出面板无报错且 PDF 页数与预期一致。4.3 中文变成方块或问号字体链路断在哪方块和问号是两种不同的失败。方块通常意味着字体被找到了但缺少对应字形问号通常意味着编码转换失败字符在进入排版引擎前就已经丢失。区分这一点能快速定位。如果是方块重点查字体。某些字体只覆盖部分汉字生僻字、繁体字、特殊符号可能缺失。解决办法是换一个覆盖更全的字体或者对特殊字符单独指定字体。如果是问号或整段中文消失重点查编码文件是不是 UTF-8、宏包参数是不是写了UTF8、编译器是不是xelatex。还有一种特殊情况PDF 阅读器自带的字体替换。某些阅读器在字体嵌入不完整时会用自己的字体渲染导致显示和实际不一致。用另一个阅读器打开对比一下能排除这类干扰。4.4 只在某个文件出问题排除法定位如果同一份配置下A 文件正常B 文件不正常问题基本锁定在 B 文件本身。排查顺序文件编码 → 文档类参数 → 是否有特殊宏包 → 是否有从别处拷来的片段。我从别处拷代码片段踩过一次坑拷来的片段里带了不可见字符编译报错指向的行看起来完全正常。这种问题用编辑器的“显示所有字符”功能能看到异常符号肉眼看不出来。所以从网页、PDF、聊天窗口拷内容进.tex文件最好过一遍纯文本编辑器或者拷完立刻编译一次别攒着。5. 提高效率的辅助配置与使用习惯5.1 编译触发方式保存自动编译与手动编译的取舍latex-workshop.latex.autoBuild.run控制自动编译行为。可选值有never、onSave、onFileChange。onFileChange最激进每次改动都触发写长文档时频繁编译会拖慢编辑器。onSave是折中方案保存时编译一次节奏刚好。我习惯用onSave配合手动快捷键补编译。{ latex-workshop.latex.autoBuild.run: onSave }写大文档时一次完整编译可能要几秒到十几秒自动编译太频繁会打断思路。这时候可以临时切成never需要看效果时手动触发。5.2 清理中间文件别让垃圾文件干扰下一次编译.aux、.log、.out、.toc、.synctex.gz这些中间文件在正常情况下会自动更新但遇到编译中断、手动改过文件、切换编译器时残留的旧文件可能导致诡异问题比如目录不更新、交叉引用错乱。清理一遍再编译往往能解决“代码没改但结果不对”的怪现象。LaTeX Workshop 提供了清理命令CtrlShiftP→LaTeX Workshop: Clean up auxiliary files。养成在切换编译器、切换文档类之后清理一次的习惯能省掉不少无谓排查。5.3 正反向搜索写长文档的必备能力-synctex1生成的同步文件支持双向跳转。正向是从源码跳到 PDF 对应位置反向是从 PDF 点击跳回源码。VS Code 里CtrlAltJ正向Ctrl 点击 PDF 反向。写几十页的文档没有这个功能定位起来非常痛苦。这个功能依赖 PDF 阅读器支持。VS Code 内置的 PDF 预览支持反向搜索用外部阅读器就不一定了。所以建议先用内置预览验证功能是否正常再决定用哪个阅读器。6. 那些文档里不写的实操心得先讲一个我踩过的坑。早些年我习惯把所有配置写在一个settings.json里后来换机器、换项目配置冲突搞得焦头烂额。后来改成工作区级配置项目根目录下的.vscode/settings.json全局配置只保留通用的部分。这样每个项目可以有自己的编译配方互不干扰。尤其是维护多个模板时这个习惯能救命。第二个心得关于编码转换。批量转换文件编码时不要一次性全转完再编译而应该转一个编译一个。原因是某些文件里可能有特殊字符转换过程会暴露问题一次性全转完你就不知道是哪个文件出的事。小步快跑出问题好定位。第三个心得关于字体。如果你的文档里要处理生僻字、古籍用字、特殊符号系统自带字体很可能覆盖不全。这时候提前确认字符覆盖范围比写到一半发现显示不出来要省事得多。可以先用一个小文档把所有需要的字符跑一遍确认无误再大规模写。第四个心得关于模板复用。从网络下载的模板先在一个空目录里单独编译一遍确认能在本机跑通再往里面填内容。直接往模板里灌内容一旦出问题你就分不清是模板的问题还是内容的问题。最后说一个判断原则中文 LaTeX 的问题九成以上落在“编码、引擎、字体”三件事上。遇到报错或者不显示别急着改宏包、改参数先按这个顺序过一遍。编码看状态栏引擎看输出面板的命令行字体看报错信息和系统字体列表。这三处都确认无误问题基本就解掉了。那些看起来复杂的报错往往只是这三条链路里某一环没对齐。
阅读完成 · 觉得有帮助?