
作为每天都在IDEA里泡着的Java开发我相信没有人没被控制台乱码恶心过。程序跑起来一堆中文日志变成•„或者????????看着头都大关键是网上搜到的解决办法五花八门照着改了一遍发现下次换个项目又乱了非常糟心。这篇文章我想把IDEA控制台中文乱码这件事彻底讲清楚。我尽量把每一个可能导致乱码的环节都梳理一遍从文件编码到运行配置再到Tomcat再到Windows系统本身每一步都会解释“为什么这么改”而不是只给一个“抄作业”式的答案。全文基于我这些年实际踩坑的经验也会把一些容易误判的地方指出来希望能帮你在五分钟内定位并解决自己的乱码问题。1. 乱码不是一种病先判断你的乱码属于哪一类很多人一遇到乱码就到处找文章今天改IDEA的编码设置明天改Tomcat的logging.properties改来改去没效果。这里我先把话说在前面控制台乱码至少有四种完全不同的成因对应的解决方式也完全不同。你第一步要做的是判断自己到底属于哪种情况而不是盲目操作。我按实际工作中最常见的场景把乱码分成四类场景典型现象核心原因编译/运行日志乱码Java程序里的System.out.println(中文)输出全是问号或者火星文JVM默认文件编码与源码/控制台编码不一致Maven/Gradle构建日志乱码构建过程里的中文提示全乱比如“BUILD FAILURE”前后的中文信息Maven运行JVM的file.encoding不对Tomcat运行日志乱码启动日志里的中文日期、日志信息乱码但业务代码输出正常Tomcat的catalina运行脚本使用的JVM编码不对控制台整体乱码整个IDEA控制台所有中文全乱连错误提示带路径全是乱码Windows控制台代码页GBK与IDEA控制台UTF-8冲突你对照上面这个表格先确认自己是哪一类。这里我特别想强调一个常见的误判很多人把“文件内容乱码”和“控制台乱码”搞混了。如果你是打开某个.java文件发现里面中文全乱那是文件本身的编码和IDEA读取编码不一致导致的属于文件编辑乱码不是本文讨论的“控制台输出乱码”。这两种问题的解决方向完全不同——文件乱码要改的是File Encoding和文件本身的编码转换控制台乱码要改的是输出环节的编码传递。怎么快速区分呢很简单如果你是运行程序时控制台里输出的中文乱而打开的代码文件本身显示正常那就是控制台乱码如果连打开的代码里的中文注释都乱了那先要把文件编码纠正过来再来看控制台问题。下面我就按这个分类逐个击破。2. 第一优先级IDEA三处编码配置必须形成闭环我见过太多项目代码文件是UTF-8IDEA的全局编码也是UTF-8但一运行就乱码。原因是什么因为IDEA里实际上有三套编码配置它们都在Settings - Editor - File Encodings这一页面上但经常有人只改了一处另外两处保持默认的GBK结果项目依然乱码。2.1 File Encodings面板里的三个下拉框打开Settings - Editor - File Encodings你会看到这一页有三个关键选项Global EncodingIDEA全局默认编码所有新项目都会继承这个值。Project Encoding当前项目的编码会覆盖全局设置。Default encoding for properties filesproperties属性文件的默认编码。先说前两个。我个人的建议是全部统一为UTF-8。因为现在几乎所有的协作开发、代码托管平台Git、Gitee、GitLab都默认使用UTF-8如果你某一个项目单独用了GBK推送到远端之后别人用UTF-8打开就是一片乱码。尤其是团队协作这个统一是底线。注意如果你的项目是从老版本仓库拉下来的源码文件本身就是GBK编码那么你强行把Project Encoding改成UTF-8会导致所有中文注释变成乱码。这种情况正确的做法是先把文件内容用IDEA的“File - File Properties - Convert Encoding”批量转换到UTF-8再调整Project Encoding。千万别反过来。2.2 隐藏很深的“Create UTF-8 files”设置File Encodings页面下方还有一个容易被忽略的地方——Create UTF-8 files选项。它隔壁还有一个下拉框默认值通常是with BOM或者without BOM不同版本略有差异。这里涉及一个关键概念BOMByte Order Mark。你新建一个Java文件时IDEA会按这个选项决定是否在文件开头写入EF BB BF三个字节。对于.java文件来说我们一般不需要BOM因为javac能正常识别无BOM的UTF-8而且有BOM的UTF-8在某些场景下比如shell脚本反而会出问题。所以选择without BOM通常更稳妥。有些教程会建议把这个设成BOM理由是Windows记事本识别UTF-8需要BOM。但你是用IDEA开发不是用记事本所以我不推荐这么做还是标准无BOM的UTF-8最省心。2.3 修改之后不是立刻生效的这里有个很关键的细节修改File Encodings不会立刻对当前已经打开的文件生效也不会立刻让控制台变正常。你修改完之后最好把IDEA完全重启或者至少关闭当前项目重新打开。因为IDEA在运行时文件编码的映射关系已经缓存在内存里了简单按一下“Apply”并不会重新解码已经打开的文件。如果你改完设置发现打开的代码文件还是乱可以试试右下角状态栏里的文件编码切换按钮点它可以直接切换当前文件的解码方式。但这只是临时查看用的千万不要用这种方式“解决”问题——它只是视觉上把文件以不同编码重新读取一遍保存时如果编码不对反而会把文件搞坏。2.4 命令行运行时的编译编码还有一个和IDEA图形界面无关但经常被忽略的点如果你用的构建工具是Maven或Gradle它们编译Java文件时用的编码是由pom.xml里的project.build.sourceEncoding属性控制的。这跟IDE设置无关是你项目的构建配置的一部分。Maven项目的pom.xml里建议显式加上properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding project.reporting.outputEncodingUTF-8/project.reporting.outputEncoding /properties加这一行是什么意思呢它告诉Maven在编译的时候源代码文件按UTF-8来读取。很多老项目的pom里没写这个属性编译时Maven会调用JDK默认编码。在Windows中文环境下JDK默认编码是GBK如果你的源码是UTF-8编译出来的class里中文就已经是乱的了运行自然也是乱的。这个坑非常隐蔽因为IDEA层面完全正常代码也没问题就是编译环节悄悄把编码搞乱了。3. 运行配置里的VM参数一句话解决大部分Java输出乱码如果第一部分的文件编码已经全部统一为UTF-8但运行Java程序时控制台里System.out.print的中文还是乱码那大概率是JVM运行时所用的默认字符集不对。这时候就要请出Java平台一个非常重要的系统属性file.encoding。3.1 为什么控制台输出“需要”文件编码很多人不理解我只是在控制台打印一句话跟“文件编码”有什么关系这也是初学者最容易卡的认知点。其实Java的System.out本质上是一个PrintStream对象它内部有编码。这个编码在JVM启动时根据file.encoding这个系统属性来决定。在Windows中文环境下JDK 8及更早版本默认的file.encoding是GBK而IDEA控制台默认按UTF-8解码收到的字节流。于是你程序里用UTF-8编码的中文字节被控制台按UTF-8解码按理说是对的但如果JVM用的是GBK编码输出控制台按UTF-8解码自然会乱。还有一个情况是JDK 18之后JEP 400把JVM的默认字符集从平台相关改成了UTF-8理论上乱码会少一些但Windows Console控制台窗口本身的代码页问题依然存在。所以解决办法还是要显式指定file.encodingUTF-8。3.2 在Run Configuration里添加VM options打开Run - Edit Configurations选择你的启动类配置比如Spring Boot的Application在VM options那一栏加上一行-Dfile.encodingUTF-8加上这一行之后JVM就会以UTF-8作为默认字符集。程序里的输出会用UTF-8编码IDEA控制台用UTF-8解码两边就对上了。这里我建议顺手把-Dconsole.encoding也加上虽然它不是标准Java属性但在某些应用服务器比如Tomcat里会起作用。你写为-Dfile.encodingUTF-8 -Dconsole.encodingUTF-83.3 为什么有时候一个配置还不够在实际项目里尤其是Maven多模块项目或者Spring Boot项目你可能会发现在Run Configuration里加了VM参数还是乱码。原因在于你的程序并不是直接在IDEA里跑的而是由Maven的spring-boot:run插件来启动的。这时你配置的VM options可能会被Maven插件的fork机制吃掉。解决办法有两个办法一改用直接运行主类的方式不用Maven插件启动。对于Spring Boot项目直接运行带有SpringBootApplication的启动类通常更可控这时你的VM options能直接生效。办法二如果一定要通过Maven启动就需要在pom.xml里给spring-boot-maven-plugin显式配置jvmArgumentsplugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration jvmArguments -Dfile.encodingUTF-8 /jvmArguments /configuration /pluginGradle项目就在build.gradle里给JavaExec配置tasks.withType(JavaExec).configureEach { jvmArgs(-Dfile.encodingUTF-8) }3.4 顺带提醒日志框架的编码也会插一脚如果你用的日志框架是Logback或Log4j2它们输出到控制台的encoder里也可能有自己的编码设置。比如Logback的控制台appender如果你没有显式设置它默认会用System.out的编码也就是跟着上面说的file.encoding走。但有些项目的配置文件里显式写了charsetGBK/charset这时候无论你怎么调JVM参数都没用因为日志框架输出的字节在控制台里已经变成了GBK。检查Logback配置文件里有没有类似的配置encoder charsetUTF-8/charset pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern /encoder确保charset写的是UTF-8而不是GBK。这是很多人怎么折腾都无效的隐藏原因之一。4. Tomcat和Web项目控制台乱码的另一个重灾区如果你是在IDEA里跑Web项目部署到内置或外部Tomcat然后发现Tomcat日志里的中文乱码这个问题的处理链路会稍微长一点。这里的“乱码”和上面说的Java程序乱码有重叠但Tomcat有自己的一套编码配置逻辑。4.1 Tomcat的启动脚本JVM编码Tomcat在Windows下是通过bin/catalina.bat脚本启动的脚本里定义了JVM参数。你可以在这份脚本里加上set JAVA_OPTS%JAVA_OPTS% -Dfile.encodingUTF-8这样Tomcat启动的JVM就会以UTF-8作为默认字符集。如果你用的是外部Tomcat修改之后需要重启Tomcat。但注意一点在IDEA里集成Tomcat时IDEA并不走catalina.bat而是直接调用Tomcat的startup逻辑。此时你需要在IDEA的Tomcat Server运行配置里找到VM options加同样的参数-Dfile.encodingUTF-8但IDEA的Tomcat配置界面里有时不太明显需要展开Server标签页底部的Startup/Connection选项卡或者在Startup script里找到JVM参数设置。不同IDEA版本界面略有差异但搜索VM options肯定能找到。4.2logging.properties里被忽略的编码配置Tomcat有自己的日志框架基于JULI即Java Logging API的扩展它的日志输出编码由conf/logging.properties控制。如果你发现Tomcat日志文件里写出来的中文乱码但控制台是好的那问题很可能出在logging.properties的encoding配置上。在conf/logging.properties中找到下面这样的配置java.util.logging.ConsoleHandler.encoding UTF-8 java.util.logging.FileHandler.encoding UTF-8如果没有就手动加上。注意这里有两个Handler——ConsoleHandler负责输出到控制台FileHandler负责写入日志文件他们的编码可以独立设置。如果日志文件乱码但控制台正常只需要设置FileHandler.encoding。4.3 请求参数乱码不算控制台乱码但很多人混淆顺便说一个容易混淆的相关问题很多人在处理“Tomcat中文乱码”时说的其实是请求参数里的中文乱码也就是客户端传过来的参数到后端变成问号。这是另一套问题跟控制台乱码完全是两码事解决方式是在Spring Boot里配置server.tomcat.uri-encodingUTF-8或者在Tomcat的server.xml里给Connector加URIEncodingUTF-8。我不建议在排查控制台乱码时被这个问题带偏。如果后端接收到的参数乱码那就去查请求链路编码如果只是日志和输出乱就按本文说的日志链路排查。这两者经常被混为一谈导致排查方向错误。4.4 内置TomcatSpring Boot需要关注启动顺序用Spring Boot内置Tomcat时启动日志其实分为两段一段是Spring Boot自身启动的日志一段是Tomcat初始化时输出的日志。很多时候你会发现Spring日志中文正常但Tomcat启动日志里那段ASCII边框加中文的提示乱码。这种“一半正常一半乱码”的情况基本是Tomcat在启动早期就初始化了日志系统而JVM的默认字符集还没被Spring Boot的配置覆盖。解决办法很直接还是在启动类的VM options里指定-Dfile.encodingUTF-8让JVM在最初阶段就用UTF-8。如果依然乱检查是否有-Duser.language这类参数被设置成了zh之外的值某些情况下user.language也会影响日志编码。5. Windows环境下绕不开的代码页问题从根源理解GBK与UTF-8之争说句实话如果你在Windows上开发遇到控制台乱码的概率就是比Mac和Linux高。这不是IDEA的锅也不是你代码的锅根源在于Windows控制台默认使用代码页936即GBK来显示字符而IDEA控制台是模拟终端窗口它自己有一套显示逻辑。这两者一旦冲突乱码几乎不可避免。5.1 从C语言时代就存在的经典问题这个问题其实从Windows命令行时代就存在了。你在Windows的cmd里运行一个输出中文的Python脚本大概率乱码运行一个输出中文的Java程序也可能乱码就连dir命令输出中文文件名在某些编码设置下也会乱。原因都一样程序输出的字节是按UTF-8编码的但cmd窗口按GBK解码或者反过来程序输出GBK字节但Windows Terminal按UTF-8解码。IDEA的控制台面板并不等同于cmd.exe它是一个Swing组件用IDE内置的渲染引擎显示文本。但这个组件本身也有编码策略它通常假定输入流是UTF-8。如果JVM输出的是GBK字节IDEA控制台按UTF-8解码就会产生乱码。5.2 新版IDEA里有没有全局开关JetBrains在IDEA 2020.1之后的某些版本里增加了对控制台编码的自动检测能力但实测下来自动检测并不总是可靠。最稳妥的方式还是在Help - Edit Custom VM Options里给IDEA自己的JVM加一行-Dfile.encodingUTF-8这里要注意这是给IDEA进程本身设置VM参数不是给你的项目设置VM参数。很多网上的教程把这一步和上一节说到的Run Configuration里的VM options混为一谈导致新手加错地方。简单区分一下IDEA的VM optionsidea64.exe.vmoptions影响IDEA本身显示包括控制台组件的底层编码。项目的VM optionsRun Configuration影响你的Java程序运行时行为。理想情况下两者都应该设置。如果只是项目里输出乱加项目的如果整个IDEA界面某些地方都乱比如Build输出、Git输出就要考虑加IDEA的VM options。5.3 Windows Terminal和PowerShell为什么乱得更少我发现很多人在IDEA里乱但切到Windows Terminal里跑同样的代码却不乱。原因是Windows Terminal默认使用UTF-8编码解码输出而且新版PowerShell会调用[Console]::OutputEncoding来设置编码。如果你用IDEA自带的终端Terminal窗口跑Maven命令它继承的是IDEA进程的环境变量这时受IDEA的编码设置影响。如果你想让IDEA自带的终端窗口不乱码可以尝试在Settings - Tools - Terminal里检查但没有一个直接的“终端编码”选项。实际做法是确保系统层面把[Console]::OutputEncoding设为UTF-8或者在IDEA终端里先执行chcp 65001这个命令会把当前控制台的代码页切换到UTF-865001。但注意这个命令只对当前终端会话有效重启之后就失效了。如果想永久生效可以在Windows的注册表或者PowerShell的$PROFILE里做设置但那是另一个话题。5.4 警惕某些CtrlC/CtrlV带来的隐藏文本最后说一个我在工作中遇到的玄学问题你从网页或者其他编辑器复制一段中文配置到IDEA里看起来正常但运行的时候就乱码。这是因为复制过来的文本里可能混入了不可见的Unicode字符比如零宽空格U200B或者不同标准的中文引号。这类问题看起来像乱码实际上不是编码问题而是字符本身就不对。遇到这种诡异情况建议先把内容粘贴到纯文本编辑器里检查或者用十六进制查看功能看看相邻字节是什么。我见过最离谱的一个案例是某同事从PDF里复制了一段配置里面用了全角空格Java编译器把它当作非法字符但IDEA里面看不出来折腾了半小时才定位到。6. 终极排查方案五步定位法五分钟找出乱码源头写到这里我把每个环节都拆开讲了一遍。但实际工作中你不可能每次都按顺序把所有设置检查一遍。所以我把排查流程浓缩成了五个步骤你按顺序执行基本能快速定位到问题环节。6.1 第一步看源文件编码打开你输出中文的那个文件看右下角的编码标识。如果是UTF-8跳过如果是GBK先把源文件Convert Encoding到UTF-8同时检查pom.xml里有没有project.build.sourceEncoding属性。这一步可以用IDEA的File - File Properties - Convert Encoding完成它会生成一个新文件你确认没问题后再覆盖原文件。6.2 第二步检查三处File Encodings确认Settings - Editor - File Encodings里的Global、Project、properties文件三处编码全部是UTF-8。这一步很容易遗漏properties文件那个下拉框很多人改了前两个第三个一直是GBK导致.properties配置文件里的中文乱码。改完后重启IDEA再测试。6.3 第三步给运行配置加VM参数在Run - Edit Configurations里找到你的运行配置在VM options里添加-Dfile.encodingUTF-8重新运行程序。如果这一步解决了说明问题出在JVM运行时编码就不用再往后查了。如果还没解决进入第四步。6.4 第四步检查日志框架编码如果你用了Logback、Log4j2或者Spring Boot自带的日志框架找到对应的日志配置文件logback.xml/logback-spring.xml/log4j2.xml/application.yml确认charset都是UTF-8。尤其注意是否有某个环境配置里把charset写成了GBK或其他编码。这一步排查完绝大多数项目的乱码都能解决。6.5 第五步最后的大招——直接看字节如果以上四步都试了还没解决那就要上硬核手段了。写一个最简单的Java程序public class EncodingProbe { public static void main(String[] args) { System.out.println(file.encoding System.getProperty(file.encoding)); System.out.println(defaultCharset java.nio.charset.Charset.defaultCharset()); System.out.println(中文编码测试); } }先看控制台输出。如果你看到file.encodingUTF-8 defaultCharsetUTF-8 中文编码测试但你的项目还是乱说明问题不在JVM编码而在IDEA控制台的显示层。这时可以试试在IDEA中打开Help - Diagnostic Tools - Compiler或者临时切换到外部终端来验证。如果输出显示file.encodingGBK说明JVM启动参数没有生效——检查是不是在Run Configuration里加错了地方或者Maven插件fork覆盖了参数。6.6 我日常预防乱码的几个习惯最后分享几个我自己养成的习惯虽然简单但真的能避免大多数乱码问题pom.xml里永远写死project.build.sourceEncoding为UTF-8。在新项目初始化的时候就把这行加上不要等出现乱码再补。控制台相关配置统一写UTF-8。不管是运行配置的VM参数、日志框架的charset还是Tomcat的logging.properties全部以UTF-8收尾。收到老项目先做编码体检。如果是从网上拉下来的老项目先全局搜索一下.properties、.xml、.java这些文件里有没有GBK编码的有的话优先批量转换掉。别轻易试网上那些“改环境变量JAVA_TOOL_OPTIONS”的建议。这个参数会全局影响所有Java程序设置成-Dfile.encodingUTF-8会导致某些老项目里的GBK硬编码文件出问题属于兜底方案不建议一开始就用。如果同一台机器上多个项目有些项目必须用GBK编码怎么办我的经验是尽量别混用。如果实在无法避免可以只给对应项目单独设置Project Encoding为GBK但要在团队内部说清楚。这种情况下VM参数那一步不要全局设UTF-8而是只在你需要的项目运行配置里加。切记IDEA的VM options是全局的一旦设了会影响所有项目的控制台解码。写在最后的一点体会以上是我在IDEA控制台乱码问题上的全部排查经验。其实这些知识拆开来看都很简单底层就是三件事源文件是什么编码、JVM用什么编码输出、控制台用什么编码解码。只要这三个环节统一了乱码问题九成以上都能解决。剩下的那一成往往是某个框架内部又做了层编码转换或者某个配置文件里隐式指定了别的字符集。遇到这种疑难杂症也不用慌按我上面说的五步定位法逐层排查配合EncodingProbe这个十几行的小工具一定能找到源头。开发工具就是这样出现一个看似低级的问题背后往往是好几层机制互相影响。你把原理搞明白了比记住一百个“把XXX改成XXX”的零碎技巧要管用得多。希望这篇文章能帮你彻底告别IDEA控制台乱码这个烦人的问题。