ARTICLE DETAIL

资讯详情

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

VSCode终端乱码怎么解决?从字符编码原理到多场景排查套路

VSCode终端乱码怎么解决?从字符编码原理到多场景排查套路 刚用 VSCode 写了个小工具跑起来一看终端里全是“灏忓寮”这种天书旁边同事还补了一刀“你这输出的是火星文吧”我说别笑VSCode 终端乱码这事儿几乎每个用编辑器写代码的人都撞上过。printf 中文糊了、Python print 出来乱掉、SSH 连上服务器看日志全是问号甚至解压个 zip 文件名都成乱码。很多人第一反应是“系统坏了”或者“替换字体”其实真凶只有一个——字符编码对不上。乱码的本质不难理解程序在内存里保存中文时会按某张“编码对照表”比如 UTF-8 或 GBK把字符翻译成字节终端显示时又按另一张对照表把字节翻译回字符。如果两张表不一致同一个字节串就会被“翻译”成完全不同的文字看起来就是一团乱码。这篇文章我不打算念教科书而是把手边的经验和排查套路一次性列出来。如果你是刚接触 VSCode 的新手或者被终端乱码折磨到想砸键盘的老哥跟着思路走一遍基本都能自愈。1. 先从根上搞懂乱码是“对照表”错位不是玄学在动手改配置之前强烈建议先花十分钟搞清楚编码到底是怎么回事。很多人卡在乱码问题上就是因为在网上搜一堆“改编码”的办法照着改完发现治标不治本过几天换个项目又乱了。1.1 字符、字节、编码三者的关系可以把字符集和编码理解成“词典”字符“中”在 Unicode 词典里的编号是 U4E2D但存到硬盘或者通过网络传出去必须变成字节。UTF-8 是一种编码方案把“中”编成 3 个字节E4 B8 ADGBK 是另一种编码方案把这个字符编成 2 个字节D6 D0。乱码发生的瞬间就是写入方和读出方用了不同的词典。比如我用 UTF-8 把“中”字变成 E4 B8 AD终端却按 GBK 去查查出来的可能是“涓”这种毫不相干的字。更惨的是如果字节序列长度不对齐后面所有字符都会连锁错位整行输出看起来就像被搅碎了一样。理解这层关系后解决乱码的思路就非常清晰了要么让程序输出的字节按照终端期望的编码来要么让终端按照程序输出的编码去解析。两边对齐乱码自然消失。1.2 先判断当前环境用的是哪张表不同操作系统、不同终端工具默认编码完全不一样。Windows 中文版系统默认活动代码页是 936也就是 GBK而 VSCode 默认走的是 UTF-8 逻辑这种“双重默认”就是 Windows 上乱码重灾区的根源。Linux/macOS 则基本都用 UTF-8出问题通常是 locale 没配对。先跑几条命令确认当前环境别一上来就瞎改Windows 命令提示符或 PowerShell 里执行chcp会显示类似936或65001的数字。65001 是 UTF-8936 是 GBK。Linux/macOS 终端里执行echo $LANG会看到类似zh_CN.UTF-8或C.UTF-8的输出。还想更精确定位的话可以把一段中文重定向到文件再用十六进制工具看字节。比如echo 测试 test.txt然后用xxd test.txt看字节能直观看到是 UTF-83 字节还是 GBK2 字节。1.3 别靠肉眼猜编码用字节说话这里分享一个我的习惯排查乱码时不要盯着乱码字符猜它是什么编码而是去看原始字节。VSCode 装一个 Hex Editor 插件打开乱码文件能直接看到十六进制内容。比如看到E6 B5 8B E8 AF 95这种 6 字节两字的结构基本可以肯定原文件是 UTF-8看到B2 E2 CA D4这种 4 字节两字的结构大概率是 GBK。用字节而不是肉眼做判断能避免大量无效操作。我见过有人把 GBK 文件反复在各种编码之间切换保存最后文件彻底损坏就是因为在瞎猜。2. Windows 下 VSCode 终端乱码最典型也最好修Windows 是终端乱码的高发区因为中文系统默认 GBK而现代开发工具几乎全面拥抱 UTF-8。两边一冲突输出必乱。下面这几种配置方式按使用场景选一种就行。2.1 临时救急一行命令切换活动代码页如果你只是临时跑个脚本想在 VSCode 终端里手动切换编码直接在终端执行chcp 65001执行完当前终端的活动代码页就变成 UTF-8 了之前因为 GBK 显示乱码的中文输出大概率立刻恢复正常。如果你需要切回 GBK执行chcp 936即可。注意chcp 65001只对当前终端会话生效新开一个终端标签页又会回到默认代码页。而且某些老程序对代码页切换非常敏感切换后可能出现文字错位甚至排版混乱临时用用可以不建议作为长期方案。2.2 长治久安把 VSCode 终端默认编码改成 UTF-8VSCode 内置终端底层用的是 Windows 控制台它默认继承系统代码页。要让每个新开的终端都自动切到 UTF-8可以在settings.json里针对 Windows 的终端配置文件做手脚打开设置Ctrl,右上角进入settings.json加一段{ terminal.integrated.profiles.windows: { Command Prompt: { path: C:\\Windows\\System32\\cmd.exe, args: [/K, chcp 65001 nul] }, PowerShell: { source: PowerShell, args: [-NoExit, -Command, chcp 65001 nul] } }, terminal.integrated.defaultProfile.windows: Command Prompt }这段配置做的事情是启动 cmd 时先执行chcp 65001并抑制提示输出。之后你每次打开 VSCode 终端活动代码页都会自动切到 UTF-8。PowerShell 那边也一样通过参数注入命令。如果你用的是 PowerShell 而不是 cmd还有个更优雅的做法在 PowerShell 配置文件$PROFILE里加两句[Console]::OutputEncoding [System.Text.Encoding]::UTF8 $OutputEncoding [System.Text.Encoding]::UTF8第一行是让控制台用 UTF-8 解码程序输出第二行是把管道里的字符串按 UTF-8 编码传给子进程。很多人在 PowerShell 里遇到 Python 输出乱码就是只设置了第一行导致输出编码和解码依然不一致。2.3 文件本身别存错files.encoding 和 autoGuessEncoding终端修好了还有一类问题来自 VSCode 编辑器本身打开一个 GBK 编码的源文件编辑器按 UTF-8 去解码代码里的中文注释和字符串直接变成乱码。这时候终端再干净也白搭因为源代码里的字符串已经废了。在设置里把这两项配置好{ files.encoding: utf8, files.autoGuessEncoding: true }files.encoding控制新建文件的默认编码files.autoGuessEncoding会让 VSCode 在打开文件时自动猜测编码遇到 GBK 文件会用 GBK 解码显示不乱码。不过我建议把autoGuessEncoding当成辅助手段不要完全依赖。因为猜编码本身就是概率事件尤其在一些混合内容文件里可能猜错导致你编辑完保存时文件被写成别的编码内容就损坏了。我的个人习惯是文件打开后先看右下角显示的编码。如果显示 UTF-8 但中文正常说明没问题如果显示 UTF-8 但中文是乱的点一下右下角选择“通过编码重新打开”手动选 GBK。确认编码正确后再编辑保存时也可以再检查一次右下角的编码。3. 程序输出乱码C/C、Python、Java 逐个击破终端编码对齐后乱码问题还经常出现在程序自身输出环节。不同语言的运行时对编码的处理方式差别很大如果你在 VSCode 里直接运行代码然后发现乱码大概率是下面某个环节出了问题。3.1 C/C源代码编码、编译器选项、运行时地区设置三件套C/C 的乱码问题最经典也最好排查。先说编译器MSVCVisual Studio 的 C 编译器在 Windows 上默认会把源码按当前系统代码页GBK解读然后编译出的程序内部字符串常量的编码也跟着走。如果你在 VSCode 里编译一个源码编码为 UTF-8 的文件但没告诉编译器中文字符串在运行时就会以错误的字节形式暴露出来。解决办法有两个一是在源码文件保持 UTF-8 的前提下给 MSVC 加编译选项cl /utf-8 main.c二是用 GCC/MinGW 的话gcc -finput-charsetUTF-8 -fexec-charsetUTF-8 main.c -o main.exe-finput-charset告诉编译器源码用什么编码-fexec-charset告诉编译器运行时可执行字符用什么编码。两条都指定 UTF-8就能保证源码里的中文在程序输出时按 UTF-8 字节流发送。还有一点容易被忽略程序运行时你可以用setlocale把 C 运行时的地区设置为 UTF-8避免某些标准库函数按本地代码页处理字符。示例#include stdio.h #include locale.h int main(void) { setlocale(LC_ALL, .UTF-8); printf(中文测试\n); return 0; }Windows 下使用.UTF-8需要系统版本支持Linux 下传zh_CN.UTF-8或C.UTF-8。实测中这句代码能解决大量标准库函数输出中文乱码的问题。3.2 Python用环境变量一劳永逸Python 3 的源文件默认按 UTF-8 解码但输出阶段在 Windows 上很尴尬。Python 的标准输出流会跟随控制台代码页如果代码页是 936print(中文)就会尝试按 GBK 输出如果此时 VSCode 终端被切到了 65001两边一冲突就乱码。最省事的方法不用在代码里加任何东西直接设置环境变量Windows打开系统环境变量新建PYTHONIOENCODING值填utf-8。Linux/macOS在~/.bashrc或~/.zshrc里加一行export PYTHONIOENCODINGutf-8。不想改全局的话也可以在 VSCode 的.env文件里配置或者临时运行set PYTHONIOENCODINGutf-8 python main.py。另一个更粗暴但有效的环境变量是PYTHONUTF81它会让 Python 在 Windows 上也默认使用 UTF-8 模式源码解码和标准输入输出全部统一为 UTF-8。这个变量在 Python 3.7 以上版本可用。顺带说一句有时候 VSCode 终端切了 UTF-8Python 依然乱码是因为 Python 启动时缓存了旧的控制台编码。改完环境变量后记得完全关闭 VSCode 再重新打开别用“重新加载窗口”糊弄过去实测经常不生效。3.3 JavaSystem.out 的编码由 file.encoding 决定Java 的乱码问题有自己的特殊点System.out的编码跟 JVM 的file.encoding参数挂钩而这个参数默认又跟操作系统的区域设置有关。Windows 中文系统上JDK 8~17 默认file.encodingGBK控制台输出中文时按 GBK 写字节如果 VSCode 终端是 UTF-8必然乱码。解决方案是在运行 Java 程序时带上 JVM 参数java -Dfile.encodingUTF-8 -jar your-app.jar如果是通过 VSCode 的 Java 插件运行可以在项目的.vscode/launch.json中给vmArgs加上参数{ version: 0.2.0, configurations: [ { type: java, name: Run Main, request: launch, mainClass: com.example.Main, vmArgs: -Dfile.encodingUTF-8 } ] }JDK 18 之后默认就是 UTF-8 了如果你用的是新版本 JDK 还乱码反而要怀疑是不是哪里强行设置成了 GBK。另外Maven 或 Gradle 项目里的编译编码也可能导致乱码在pom.xml里加一句project.build.sourceEncodingUTF-8/project.build.sourceEncoding是常规操作。3.4 跨语言统一思路能设 UTF-8 就别用别的不管你用什么语言最好在项目层面就定下一个规矩所有源码文件、构建脚本、终端配置、运行时参数一律 UTF-8。团队项目尤其如此——如果一个人用 GBK 保存源码另一个人用 UTF-8 打开另存git 提交时会看到一堆无意义的字符改动溯源非常痛苦。现在主流编辑器、编译器、云平台都围绕 UTF-8 做了默认支持与其琢磨怎么各个击破不如在一开始就对齐。4. Linux/SSH/跨平台场景locale 与远程终端编码跨平台环境下的乱码问题经常让人摸不着头脑因为在 Windows 上排查完换个 Linux 服务器又乱了。这类问题的核心在于终端背后的字节解析规则跟远程系统的 locale 设置以及本地终端软件的字符集设置三者必须串成一条线。4.1 Ubuntu 和常见 Linux 发行版的 locale 检查Linux 下的乱码大多不是“编码不对”而是系统缺少对应的 locale。比如你在 Ubuntu 上跑一个输出中文的程序终端显示?????或者直接报 locale 错误多半是LANG没设对或者zh_CN.UTF-8根本没有生成。先检查locale locale -a如果输出里只有C.UTF-8没有zh_CN.UTF-8你可以临时用export LANGC.UTF-8试试中文输出大概率正常。要长期改的话编辑/etc/default/locale或当前用户的~/.bashrcexport LANGzh_CN.UTF-8 export LC_ALLzh_CN.UTF-8注意一个问题很多程序输出中文时实际用的是LC_CTYPE或LC_MESSAGES而不是整个LC_ALL。如果只想保底设置LANGC.UTF-8其实是最稳的因为它保证系统基础 locale 是 UTF-8 编码又不强制本地化语言。中文照样能显示只是界面提示是英文这对我来说完全够用。4.2 SSH 远程终端乱码两边都要查通过 VSCode 的 Remote-SSH 插件连上远程服务器打开远程文件终端跑命令输出中文乱码这种场景很常见。本质是远程程序按远程系统的编码输出字节本地终端工具按自己默认的编码解码两条链路只要有一端不对称就乱。排查和修复顺序我的经验是从远到近先确认远程系统的 localeecho $LANG如果不是*.UTF-8按上面方法修改/etc/default/locale或~/.bashrc。确认 VSCode 的终端配置Windows 本地按照上文把代码页切到 65001Linux/macOS 本地检查终端的字符集设置一般都选 UTF-8。如果远程跑的是 Java 程序别忘了设置JAVA_TOOL_OPTIONS-Dfile.encodingUTF-8这个环境变量比在启动命令里手动加参数更省心因为它对所有 JVM 进程生效。这里提一个很多人忽略的细节SSH 协议本身不负责字符编码转换它只是透明地传输字节。所以不要指望“换个 SSH 工具”就能解决乱码。你换的只是本地解码端真正的问题可能在远端。4.3 解压文件时遇到文件名乱码“Linux 解压文件乱码”这个话题在搜索热词里经常看到。Windows 下用压缩软件打包 zip 时文件名常按 GBK 编码Linux 自带unzip默认按 UTF-8 解压于是文件名里的中文全变成乱码。两种解决办法指定解压编码unzip -O CP936 file.zip-O参数让 unzip 用 CP936GBK去解码文件名。不同版本的 unzip 支持情况有差异某些旧版可能不认这个参数可以先升级 unzip。先解压再转码文件名convmv -f GBK -t UTF-8 --notest -r ./convmv 是专门转换文件名的工具--notest表示真正执行而不仅是预览。这个办法适合已经解压了一堆乱码文件的场景不用重新解压。另外直接用 7-Zip 打包的话在 Linux 上解压之前可以先看一下包的字符集信息。很多工具在打包时根本就没存编码标记全靠解压端猜所以源头规范很重要跨平台传文件时尽量用 UTF-8 规范打包。5. 文件内容乱码识别、打开、无损转换终端乱码解决之后还有一个高频场景是“打开文件就乱码”。VSCode 里打开一个项目配置文件中文注释全是乱码或者运行环境日志文件用 GBK 编码直接双击打开也是乱的。这种情况不属于终端链路而是单纯的文件编码问题。5.1 VSCode 右下角的三步操作VSCode 对文件编码的处理其实做得不错只是很多人不知道入口在哪。右下角状态栏会显示当前文件编码比如UTF-8或GBK点一下会出现一个操作菜单通过编码重新打开Reopen with Encoding手动选一种编码让编辑器重新加载文件不改动磁盘上的文件。通过编码保存Save with Encoding把当前内容按指定编码另存到磁盘会改变文件字节。处理乱码文件时强烈建议先用“通过编码重新打开”选一个你觉得正确的编码看看内容是否正常。确认没问题后再考虑是否“通过编码保存”成 UTF-8完成转换。5.2 必装的编码识别辅助如果完全不知道文件是什么编码除了用file -i命令还可以靠 VSCode 的自动猜测。设置里把files.autoGuessEncoding: true打开然后重新打开文件VSCode 会先按常见编码试探着解码。虽然不能保证 100% 准确但改对这个设置之后90% 的历史遗留文件都能直接正常显示。注意一点autoGuessEncoding 猜错的时候你看到的内容是“正常”的但实际编码不对。一旦这种情况下编辑并保存文件会被写坏。所以碰到重要文件我会先用 Hex Editor 插件瞄一眼字节序判断有没有 BOM再结合文件内容判断编码。UTF-8 文件的 BOM 是EF BB BFGBK 没有 BOM 概念如果文件开头没有 BOM 但中文正常大概率是本地化编码需要根据来源判断是 GBK 还是 Big5。5.3 文件无损转码的通用命令跨平台处理文本文件时最简单的转码命令是iconv。比如把一个 GBK 编码的文件转成 UTF-8iconv -f GBK -t UTF-8 old.txt new.txt注意重定向不能和输入文件同名否则会把原文件清空。我踩过一次这个坑后来每次都先写 new.txt确认内容没问题再覆盖原文件。PowerShell 下也有类似命令比如Get-Content -Encoding Default配合Out-File -Encoding UTF8。不过在 Windows 上我更推荐用 VSCode 的“通过编码保存”功能图形界面不容易出错。6. 排查乱码的速查表和我踩过的那些坑乱码问题在网络上搜往往得到零碎的方案。下面按“现象 - 原因 - 解决”的次序整理一张速查表你在排查时可以直接对照少走弯路。现象常见原因处理方式中文变成“涓枃”类的生僻字UTF-8 字节被 GBK 解码终端执行chcp 65001或把 VSCode 终端默认切到 UTF-8中文变成“锟斤拷”UTF-8 字节被转换为 UFFFD 后再编码显示检查文件是否被多次转码用原编码重新打开不要让 autoGuessEncoding 乱写入中文变成“????”终端或系统 locale 不支持中文Linux 设置LANGzh_CN.UTF-8或C.UTF-8Windows 检查代码页Java 程序控制台中文乱码file.encoding默认跟随系统代码页启动加-Dfile.encodingUTF-8或设置JAVA_TOOL_OPTIONSPythonprint中文乱码Python 按 GBK 输出到 UTF-8 终端设置PYTHONIOENCODINGutf-8或PYTHONUTF81C/C 源码编译后中文乱码源码编码、编译选项、运行 locale 不一致编译器加/utf-8或-fexec-charsetUTF-8运行时setlocale打开 GBK 文件在 VSCode 里乱码编辑器按 UTF-8 解码 GBK 文件右下角“通过编码重新打开”选 GBK配置autoGuessEncodingLinux 解压 zip 文件名乱码zip 文件名是 GBKunzip 按 UTF-8 解析unzip -O CP936 file.zip或convmv转码SSH 远程输出乱码本地终端与远程 locale 不一致统一远端 locale本地终端选 UTF-8Windows 执行chcp 65001串口工具minicom输出乱码串口波特率或编码设置不对检查串口连接参数minicom 中设置终端编码与发送端一致中文场景选 UTF-8 或 GBK 再试6.1 VSCode 终端启动报 conpty 相关错误VSCode 在 Windows 上偶尔会报“终端进程启动失败: 启动期间发生本机异常(无法启动 conpty)”并出现一堆诡异的输出。这个问题的本质是 Windows 控制台新架构ConPTY和 VSCode 终端组件之间出了兼容性问题不是编码问题但表现上很像“终端坏了”。处理经验打开设置搜索terminal.integrated.useConpty把它设为false然后重启 VSCode。这会强制 VSCode 使用旧版终端架构虽然某些特性比如鼠标事件、原生选项卡会受影响但胜在稳定。检查你设置里的终端配置文件的 command 路径有时候错误配置会导致终端进程起不来比如指向了不存在的 shell 路径。把terminal.integrated.profiles.windows里的配置简化成Command Prompt: {path: cmd.exe}再试。如果以上都不行直接把 VSCode 的终端“恢复默认设置”再配置。很多时候你折腾了太多配置反而引入新问题。winpty 的问题跟这个类似winpty 是一个让 MSYS2/Cygwin 程序在 Windows 控制台下正常工作的兼容层。如果你在 VSCode 终端里跑 Git Bash 脚本时乱码或报错旧版 VSCode 会尝试自动找 winpty版本不匹配时就会出问题。我的建议是更新 VSCode 到最新版然后把终端配置文件里的 shell 路径指向C:\Program Files\Git\bin\bash.exe不要用sh.exe很多奇怪现象自然消失。6.2 数据库导出和字节流工具的乱码搜索热词里出现了DataOutputStream乱码这里多说一句。DataOutputStream是 Java 的二进制输出流它本身不包含字符串编码概念——你往里面写字符串时实际上是先用某编码把字符串转成字节再写入。所以遇到这种流输出的文件乱码关键在于写入时的编码参数。比如byte[] data str.getBytes(UTF-8); out.write(data);读取时也用 UTF-8 解码。如果在代码里没有显式指定编码默认会使用运行环境的 file.encodingDB 导出的数据一旦换了环境就会乱。所有写字节流的代码我都建议显式指定 StandardCharsets.UTF_8。数据库连接串里加characterEncodingutf8也是老生常谈。无论是 MySQL 还是 PostgreSQL只要项目里出现中文乱码不要只查终端连接串、表字段字符集、驱动版本一个都别放过。6.3 专业工具FPGA 开发环境等中文注释乱码像 Vivado 这类专业开发工具中文注释乱码也很常见。这类工具跨平台、跨版本很多默认还是 GBK 偏好。处理思路其实跟前面一致源码文件用 UTF-8 保存然后到工具设置里找“文件编码”或“编辑器编码”选项改成 UTF-8。如果工具支持环境变量也可以设置语言相关变量强制 UTF-8。这类工具的乱码基本不涉及终端链路纯看工具对文件编码的解读所以在编辑器和工具之间保持一致就好。6.4 一次排查乱码的完整顺序最后把排查乱码问题的完整顺序梳理一遍大家照着做就行先复现乱码确认是终端输出乱码还是文件内容乱码还是终端本身都起不来。如果终端正常但输出乱用chcp或echo $LANG确认终端编码。确认程序输出编码查语言运行时Python 环境变量、Java file.encoding、C/C 编译选项。再确认源码文件编码VSCode 右下角看编码必要时 Hex Editor 看字节。跨平台SSH、远程文件、zip 包时把远程 locale 也纳入检查。全部改完后完全重启 VSCode不要只重载窗口。这套流程我走了很多遍每次都能准确定位到某一层的问题。其实只要把“写入端编码”和“读取端编码”这条链路想明白乱码问题基本不可能难住你。我个人在实际操作中的体会是乱码不是一个需要反复救火的日常问题而是一开始就要定好规矩的系统工程。新项目从建目录起就统一 UTF-8编辑器、终端、编译器、数据库连接串、远程服务器 locale全部控制在同一个编码标准下后续几乎不会再遇到乱码。如果是维护老项目遇到一个 GBK 文件就转一个别把 UTF-8 和 GBK 混着用免得越改越乱。最后再分享一个小技巧遇到看不懂的乱码字符先别急着删。把乱码内容复制下来去浏览器里搜一下那串“天书”经常能直接定位到它原本的编码。比如搜“锟斤拷”你会看到铺天盖地的编码转换教程这本身就是最有名的“乱码指纹”。用好这类指纹再配合本文的排查顺序你也能在几分钟内解决问题。
返回列表