十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

IDEA+Tomcat控制台中文乱码根治:字符编码统一方案

IDEA+Tomcat控制台中文乱码根治:字符编码统一方案 用 IDEA 开发 Java Web 项目启动 Tomcat 时控制台输出一堆中文乱码这几乎是每个刚接触 Spring MVC 或者 SSM 框架的同学都撞过的坑。乱码看起来是小事但真正排查起来涉及的环节一点都不少源文件编码、JVM 启动参数、IDEA 控制台解码方式、Tomcat 自身的日志输出配置任何一个环节没对齐都会让你看到满屏的鸡同鸭讲。这篇文章不只给一个改这里就好的结论而是把这套乱码的来龙去脉、排查顺序、配置原理拆开讲清楚。适合正在用 IntelliJ IDEA 开发 Java Web 项目、被控制台中文乱码折磨的同学也适合想真正理解字符编码机制、避免下次再踩坑的朋友。我尽量用大白话讲保证新手能跟上也保证老手能有所收获。1. 乱码问题的本质编码和解码用了两本密码本1.1 字符编码到底是什么字符编码这个概念简单说就是一套字符和二进制数字之间的映射规则。我们平时看到的中这个汉字在 GBK 编码下对应一组十六进制字节在 UTF-8 编码下又对应另一组字节。就好比同一个词在中文密码本和英文密码本里查到的代码是不一样的。那乱码是怎么产生的就是写入的时候用 A 密码本GBK把汉字翻译成了字节读取的时候却用 B 密码本UTF-8把这些字节翻译回字符翻译结果自然就是一堆毫无意义的符号。你看到控制台上的锟斤拷涓婁紶問棏这些经典乱码本质上都是解码用错了字符集。这里有一个很多新手容易忽略的点ASCII 码范围内的英文字母、数字、半角标点在 GBK、UTF-8、ISO-8859-1 这些常见编码里是完全一致的所以英文从来不会乱码。只要控制台输出的全是英文就说明字节传输没问题问题一定出在中文字符的解码上。这个特性也可以反过来帮助定位问题。1.2 IDEA 控制台输出中文要经过三个环节一个 Java Web 项目从代码到控制台显示中文字符要经过三个独立的编码环节环节一源文件的保存编码。你的 Java 文件、配置文件是用什么编码写入磁盘的这决定了硬编码的中文字符串在字节层面长什么样。环节二JVM 运行时的默认编码。JVM 启动时读入源文件、处理字符串以及 System.out 输出时都依赖一个默认字符集。这个默认字符集在 Windows 上通常取系统区域设置中文系统就是 GBK但也可以被 -Dfile.encoding 参数覆盖。环节三IDEA 控制台的解码编码。Tomcat 通过 System.out 把日志输出到 IDEA 捕获的流里IDEA 再按某个字符集把字节转成界面上的文字展示给你看。任何一个环节和另外两个不一致控制台就会出现乱码。这就是为什么网上搜IDEA Tomcat 乱码会出来各种各样的解决方法因为大家乱码的环节可能根本不同。有人改了 IDEA 的 File Encoding 就好了有人改了 VM Options 才解决有人调的是 Tomcat 的 logging.properties原因是他们卡在不同的环节上。1.3 为什么 Windows 上这个问题尤其明显如果你用的是 macOS 或者 LinuxIDEA 和 Tomcat 乱码的概率会低很多因为这两个系统的默认字符集基本都是 UTF-8三环节天然对齐。但 Windows 中文版系统默认的 ANSI 代码页是 GBK代码页 936而新版 IDEA 和 Tomcat 的日志模块普遍默认按 UTF-8 输出。两个体系默认值不同就导致 Windows 成了乱码重灾区。打个比方写信的人默认用简体收信的人默认用繁体两边谁也不通知谁收到信自然是满纸错别字。理解了这一点你就明白为什么解决乱码的核心思路只有四个字统一编码。把三个环节全部统一到 UTF-8或者全部统一到 GBK都能解决问题。我的建议是全部统一到 UTF-8因为这是跨平台最稳妥、也最不容易在后续部署到 Linux 服务器时出问题的方案。我在这里直接给出我的判断依据在开发环境统一 UTF-8你后续把项目部署到 Linux 服务器时几乎不用再管编码问题如果开发环境用 GBK部署到 Linux 就非常容易踩乱码坑因为在 Linux 上几乎不可能保证 GBK 环境。所以宁可花点时间把开发环境的 UTF-8 配齐也不要贪图省事改成 GBK。2. 动手定位先分清楚是哪一种乱码2.1 三种常见的乱码形态面对乱码第一个动作不是急着翻设置而是先看乱码出现在哪里。根据我的经验Tomcat 相关乱码通常可以分成三类第一类IDEA 控制台乱码。启动 Tomcat 时红色 ERROR 日志、[INFO] 前缀、Servlet 容器自身的输出都变成乱码。第二类代码里 System.out.println 输出的中文乱码日志文件里记录的内容却是正常的。第三类控制台正常但 Tomcat 日志文件比如 catalina.out、localhost.log里保存的内容是乱码。这三类乱码的根源不太一样。第一类很可能是 IDEA 控制台解码用的字符集和 JVM 输出字符集不一致第二类通常是源文件编码或 JVM 编码的问题第三类则几乎可以锁定在 Tomcat 的日志模块配置上。花两分钟观察清楚属于哪一类能省下大量瞎试的时间。2.2 第一件事确认 JVM 实际运行的编码很多人一上来就改设置结果改了半天没效果因为根因根本不在设置里。我建议的排查顺序非常固定先确认 JVM 启动时的实际默认编码。方法很简单在项目启动类里加一行输出System.out.println(当前JVM默认编码 System.getProperty(file.encoding));如果你的代码还没跑到这一行就乱码了也可以写一个独立的测试类不经过 Tomcat直接在 main 方法里输出public class EncodingCheck { public static void main(String[] args) { System.out.println(中文测试当前默认编码 System.getProperty(file.encoding)); System.out.println(控制台输出编码 System.getProperty(sun.jnu.encoding)); } }在 IDEA 里直接右键 Run 这个类观察输出。正常情况下你会看到两个结果如果输出是正常的中文测试说明 IDEA 直跑 Java 程序时编码是通的。如果输出是乱了那问题基本可以确认在 IDEA 自身的编码配置或 JVM 参数缺失。这一点非常关键如果你用了 -Dfile.encodingUTF-8输出里应该显示 UTF-8如果是 GBK那说明 JVM 用了系统默认。你接下来的所有修复动作都要以这个输出为基准来调整。2.3 用排除法定位到具体环节如果直跑 Java 程序输出正常但通过 Tomcat 启动就乱码那问题范围就缩小到了 Tomcat 启动流程相关配置。接下来看 Tomcat 的启动日志在写入文件后是什么状态找到 Tomcat 的 logs 目录打开 catalina.日期.log 文件用文本编辑器查看。如果日志文件内容正常只有 IDEA 控制台乱码说明 JVM 和 Tomcat 日志模块都没问题问题出在 IDEA 控制台的解码方式上。如果日志文件本身就是乱的说明 JVM 输出时的编码就已经不对了重点检查 Tomcat 启动脚本里的编码参数。如果日志文件里中文正常但乱码符号是锟斤拷这类特殊字符说明文件中被写入了非 UTF-8 字符常见于 Windows 系统把系统区域编码的日志追加到了 UTF-8 文件里。用这样的排除法基本一轮就能定位到乱码源头而不是靠瞎蒙去改设置。我在实际工作中多次用这套方法帮同事排掉乱码问题最快的一次三分钟就解决了。接下来我会把最终的完整配置方案写出来。这些方案是经过多台机器验证过的覆盖了绝大部分 Windows IntelliJ IDEA Tomcat 的组合场景。3. 完整解决步骤五处配置逐一对齐3.1 第一步统一 IDEA 的项目与全局编码打开 IDEA 的进 File → SettingsWindows 界面或 IntelliJ IDEA → PreferencesmacOS搜索File Encodings进入后把三处的值都改成 UTF-8Global EncodingUTF-8Project EncodingUTF-8Properties Files 下的 Default encoding for properties filesUTF-8这三个地方分别控制 IDEA 打开文件时默认用哪种编码去读、新建项目时默认用哪种编码保存文件、properties 配置文件用哪种编码读取。改完之后右下角状态栏会显示文件的当前编码你可以逐个检查已有的 Java 文件是否真的被以 UTF-8 读取。如果某个文件右下角显示的不是 UTF-8点击该位置选择Reload in UTF-8或者Convert to UTF-8注意这两个选项的区别Reload 是重新按 UTF-8 读取不会改文件内容Convert 是把文件内容从当前编码转换并按 UTF-8 保存会实际修改文件字节。如果你的项目里已经存在大量 GBK 编码的文件建议用 Convert 转换一下否则就算 IDE 配置全改了源文件字节本身还是 GBK编译进 JVM 的中文串照样是 GBK 字节。3.2 第二步给 IDEA 的 JVM 加 UTF-8 参数这一步是最容易被忽略的。IDEA 本身也是一个 Java 程序它读取控制台流、解析构建输出时也有一个自己的默认编码。在许多 Windows 环境中IDEA 自身进程的默认编码是系统区域编码GBK这就导致即使项目所有文件都是 UTF-8控制台仍然可能乱码。解决方法Help → Edit Custom VM Options打开 idea64.exe.vmoptions 文件在末尾追加一行-Dfile.encodingUTF-8然后完全退出 IDEA 并重新启动。为什么强调完全退出而不是关闭项目窗口因为 IDEA 的文件修改和日志产生的进程在关闭项目窗口后仍然驻留只有从任务管理器或 File → Exit 完全退出后新的 VM 参数才会生效。追加这个参数后IDEA 自身按 UTF-8 解码所有控制台流配合前面第一步的项目编码控制台中文的显示一般就正常了。这是整个解决流程里收益最高的一步。注意修改 vmoptions 文件时不要动其他自带参数特别是 -Xmx 这类内存参数。这个文件直接由 IDEA 管理如果改出问题IDEA 可能无法正常启动。建议修改前先备份或者严格只追加新行。3.3 第三步调整 Tomcat 自身的日志输出编码如果 IDA 的设置和 VM 参数都改完了控制台依然还是乱码那么问题很可能在 Tomcat 自身的 logging 模块。Tomcat 从 8.5 版本开始默认日志编码默认按 UTF-8 输出但 Windows 的 IDEA 控制台如果解码用的还是旧设置两边就会打架。有两个方法选一个适合你的方法一推荐打开 Tomcat 安装目录下的 conf/logging.properties找到类似下面这一行java.util.logging.ConsoleHandler.encoding UTF-8如果你想强制让 Tomcat 按 GBK 输出到控制台把它改成java.util.logging.ConsoleHandler.encoding GBK但我的推荐是保持 UTF-8 不动而是去解决 IDEA 侧的解码因为前面第 3.2 步已经把 IDEA 的 VM 参数设置成 UTF-8 了。如果你改了 IDEA 侧还是乱码再把 Tomcat 侧改成 GBK 对齐 Windows 区域也行但要记住之后你把这个 Tomcat 搬到 Linux 上日志中的中文就会变成乱码。方法二在 Tomcat 的 bin/setenv.bat 里增加 JVM 参数。如果没有这个文件手动新建一个。在文件中写入set CATALINA_OPTS%CATALINA_OPTS% -Dfile.encodingUTF-8用 setenv.bat 的好处是它不修改 Tomcat 自带的 catalina.bat升级 Tomcat 版本时不会被覆盖。我强烈建议用独立 setenv.bat 而不是直接改 catalina.bat这是能让你少踩很多坑的习惯。3.4 第四步检查并修正 Tomcat 启动脚本中的编码参数很多人改了 IDEA 的 VM Options 就以为完事了其实 Tomcat 启动时未必继承 IDEA 的 VM Options。Tomcat 是通过 IDEA 拉起 catalina.bat 脚本启动的启动脚本里如果没有显式指定编码参数JVM 的默认编码还是跟随系统区域设置也就是 Windows 上仍然是 GBK。这也是为什么光改 IDEA 的 VM Options 有时解决不了 Tomcat 乱码IDEA 自身解码没问题了但 Tomcat 的 JVM 输出到控制台的字节本身就是 GBK 的IDEA 按 UTF-8 解照样乱。如果你发现 3.3 里的 setenv.bat 方法不够或者你想在 IDEA 内置的 Tomcat 配置里就搞定可以在 IDEA 的 Run/Debug Configurations 里找到当前 Tomcat 配置的 Configuration 或 VM options 输入框追加-Dfile.encodingUTF-8注意位置这是在 Tomcat 启动配置里的 VM options不是在 IDEA 的全局 VM Options。这两者作用范围完全不同前者只作用于 Tomcat 子进程后者作用于 IDEA 主进程。两个都要配缺一不可。3.5 第五步验证配置是否生效配置完成后重启 IDEA完全退出后重新打开重新启动 Tomcat。这时再做一次验证看控制台的 Tomcat 启动日志中文是否正常。在代码里输出一段中文比如 System.out.println(中文输出测试)看控制台是否正常。打开 Tomcat 的 logs 目录下的 catalina.日期.log确认日志文件里的中文也是正常的。做到这一步三个环节全部对齐乱码问题基本就解决了。我发现很多人走到第 3.2 步就已经成功了只有少数情况需要动 3.3 和 3.4。判断是否需要继续往下走的标准非常简单重启之后看一眼控制台乱码消失了就说明你需要的配置已经到位不需要盲目把后面所有步骤都做一遍。4. 常见问题与排查技巧实录4.1 改了 File Encodings 还是乱码问题出在哪这是我在社区看到最多的反馈。原因主要有两个一是只改了 IDEA 的项目编码但 IDEA 自身进程的 VM Options 没有加 -Dfile.encodingUTF-8导致控制台流的解码还是系统默认二是改了配置后没有完全退出 IDEA只是关闭了项目窗口配置没有真正生效。判断方法也很直接重新打开 IDEA 后随便找一个已经存在的 UTF-8 中文文件如果打开是正常的说明 File Encodings 没问题再在控制台跑一个输出中文的 Java main 方法如果还是乱码那基本上就是 VM Options 的问题。按这个思路排查基本能一步到位。4.2 只有 Tomcat 启动日志乱码自己代码输出正常这种局部乱码其实很好判断如果自己的 System.out.println 中文正常说明源文件编码、JVM 编码、IDEA 控制台解码都通了。但 Tomcat 启动时的日志比如 INFO: Server startup in xxx ms乱码原因多半出在 Tomcat 自己的 java.util.logging 配置上。最典型的场景是Tomcat 的 ConsoleHandler.encoding 和 JVM 的系统默认编码不一致。Windows 中文系统下Tomcat 的 logging.properties 里如果把 ConsoleHandler.encoding 设成了 UTF-8而 JVM 实际默认是 GBK这里的字节流就会打架。解决办法就是把 Tomcat 的 ConsoleHandler.encoding 改成 GBK和 JVM 默认一致或者反过来给 JVM 加 -Dfile.encodingUTF-8推荐。这一步做完Tomcat 自身日志就正常了。4.3 为什么有些中文能正常显示、有些却乱码这个现象的根源也很有意思。如果你看到的是部分中文正常、部分乱码不要怀疑人生这大概率是文件内容里混用了不同编码。比如你的 Java 文件本身是 GBK 保存的但你在某次编辑时IDEA 可能把新插入的一段内容按 UTF-8 保存了进去文件就变成了混合编码。出现这种情况后只改 IDEA 的设置是解决不了的需要对文件做统一转码。在 IDEA 右下角点击编码区域选择 Convert to UTF-8IDEA 会按它当前识别的编码读取并转换为 UTF-8 保存。注意转换前最好做一次备份因为万一 IDEA 对文件的识别是错的转换后内容会变得更乱。我一般转换前先复制一份到临时目录确认没问题再删掉备份。4.4 乱码排查速查表我把上面所有的排查思路汇总成一个表格方便大家对照排查。现象可能性最大的环节首选修复动作启动 Tomcat 后全部中文乱码英文正常IDEA 控制台解码或 JVM 编码给 IDEA 的 vmoptions 加 -Dfile.encodingUTF-8重启自己代码的 System.out 中文乱码日志文件正常源文件编码或 JVM 编码检查源文件编码并转换为 UTF-8设置 -Dfile.encodingUTF-8只有 Tomcat 容器日志乱码自己输出的中文正常Tomcat 的 java.util.logging 配置调整 conf/logging.properties 的 ConsoleHandler.encoding 或 setenv.bat控制台正常日志文件里中文乱码日志写入时编码与文件打开编码不一致统一日志模块编码避免混用 UTF-8 和 GBK部分中文正常部分乱码单个文件内部混用了多种编码用 IDEA 转换为统一 UTF-84.5 一个能少走弯路的小工具技巧在 Windows 下排查编码问题时命令行工具 chcp 很实用。在 CMD 里输入 chcp会告诉你当前控制台的代码页。936 表示 GBK65001 表示 UTF-8。在排查乱码时你可以借此确认操作系统层面的默认代码页从而推断 JVM 在没有显式参数时的默认编码。但要注意chcp 切换的只是 cmd 窗口的代码页不会改变 IDEA 或 JVM 的行为。所以它更适合用来辅助判断系统默认值而不是用它来修复乱码。我见过有人以为把 cmd 改成 65001 就能解决 IDEA 乱码折腾了半天才发现两者毫无关系。整个解决乱码问题的心法其实就一句话找到输出字节时用的编码和读取字节时用的编码让它们保持一致。思路清楚了再乱的环境也能一步步拆解。最后再分享一点个人经验。我自己第一次遇到这个乱码问题时也是从网上抄了一堆配置改完发现有时好有时坏根本原因就是没搞懂原理。后来我把三环节的概念理清楚再遇到乱码就按先定位是哪个环节再动手改配置的顺序走基本没有失手过。如果你看完这篇文章发现自己的场景和我描述的不完全一样建议你也先不要急着改所有配置而是用一个简单的 main 方法输出中文一层层确认 JVM、IDEA、输出流这三者的编码状态。只要定位准确修复动作通常都特别简单。真心希望这篇文章能帮你一次解决 Tomcat 控制台乱码不再在这个小问题上反复折腾。
返回列表