背景
乱码问题, 最初只是因为搜遍全网搜不到有效的解决方式而做出的一篇还算不错的博客, 但是写完博客之后总觉得博客中的逻辑不够清晰, 而且篇幅太长, 于是想着优化一下.
优化过程中又不知不觉补充些内容, 之后篇幅很长, 可又觉得描述的不够, 于是分成两篇文章, 可两篇文章每篇依然太长, 于是打算分成三篇来写.
- 乱码问题(原理篇) ==> IDEA控制台乱码原理性深入研究分析与解决方案
- 乱码问题(研究篇) ==> 待定
- 乱码问题(解决方案篇) ==> IDEA控制台乱码问题,原因&解决方式,解决不了算我输
顺便说下, 本篇只偏重编码配置思想说明, 具体解决方案请看
乱码问题(解决方案篇)
统一编码配置思想
输出位置 | 编码方式 | 原因 |
---|---|---|
开发文件 | UTF-8 | 为了和其它同事共同开发代码, 防止出现编码问题. |
输出的 log 日志文件 | UTF-8 | 为了便于和其它电脑对接, 和其它系统对接, 以及文件传输 |
控制台 | 系统默认编码 GBK | 仅仅在自己电脑控制台显示, 对接系统的默认编码(中国区一般是 GBK). |
简而言之, 开发文件编码和输出到文件的编码使用
UTF-8
, 控制台日志直接使用系统默认编码GBK.
统一编码配置行为(以Java Web为例)
-
配置源代码文件, 源配置文件等编码格式为UTF-8.
当然这里如果你的项目想要使用其它编码也未尝不可, 这里对你的日志乱码没有任何影响.
但是当你的项目代码被其它项目重用的时候, 在同一个IDE中打开难免会造成不方便. -
去除开发环境(如 IDEA, Eclipse)中各种编码的配置, 直接使用默认即可.
操作系统是GBK就用GBK, SDK, IDE 等开发环境直接使用缺省(默认)配置即可.
我们要尽量少的去更改原有的编码配置, 由我们来适应操作系统
,IDE
,SDK
, 而不是强迫修改它们的配置来适应我们. -
如果你有使用tomcat服务器的话, 需要更改下tomcat的配置, 因为tomcat默认编码配置和操作系统, SDK, 以及IDE不兼容.
tomcat默认输出全是UTF-8, 与系统默认GBK不兼容, 这样当你直接使用命令行启动tomcat势必会出现乱码, 在IDE中启动也很容易造成乱码问题.
照着上面的编码思想, 文件输出使用UTF-8
, 控制台输出使用Os默认编码GBK
即可 -
log 框架日志配置一定要加上编码配置.
log日志实现框架五花八门, 在你不指定输出编码配置的时候, 有的版本log日志框架会自动使用系统的默认GBK编码(如log4j一些版本), 有的log日志框架会自动使用获取JVM
file.encoding
参数的默认编码(如log4j2一些版本).
照着上面的编码思想, 文件输出相关的Appender
编码配置指定使用UTF-8
, 控制台输出相关的Appender
编码配置指定使用Os默认编码GBK
即可
90% 的日志乱码问题应该修改的都是log配置文件, 而不是修改IDE
编码配置以及SDK
参数迫使其来适应乱七八糟的日志框架
以及五花八门的log配置文件
.
关于输出日志到文件
和 输出日志到控制台
相关个人感悟
-
字符流和字节流
而java语言在传递字符串的时候有两种方式, 一种是字符流, 一种是字节流.
为了简单理解, 字符流可以理解为
char
的传输, 字节流可以立即为byte
的传输.使用字符流可以直接直接将String中的
char[]
传送一下就可以了, 而使用字节流的话, 需要先将char[]
转换为byte[]
, 再将byte[]
传输.简单说明一下, java里面日志在输出之前肯定都是
String
字符串, String字符串内部就是一个char[]数组, String里面有一个getBytes()方法, 就是将内部的char[]按照file.encoding
的编码转换成byte[]
数组.因此使用字符流比字节流要少一步编码转换工作, 字符流比字节流更加快速, 但是对编码也更加敏感, 字节流能够与
file.encoding
完美适配, 更能输出正确的编码来. -
输出日志到文件
和输出日志到控制台
一般来说
输出日志到控制台
只用于个人电脑开发环境的调试, 对于一个项目生产环境上的日志输出到文件
中持久化是比较通用的做法.输出日志到控制台
一般不会在意日志性能问题, 而输出日志到文件
是会在意性能问题的.因此
输出日志到文件
一般使用字符流,输出日志到控制台
一般使用字节流.System.out.println() 使用的是字节流, 会自动根据 file.encoding 参数自动调整编码格式, 对编码处理时更加能够适应 JVM 配置的编码正确传送流数据,
log 日志使用的是字符流
tomcat 使用的是字符流
附录
log配置文件编码
-
log4j.properties
配置log4j.appender.haha=org.apache.log4j.RollingFileAppender log4j.appender.haha.File=haha.log # 编码加在这里 log4j.appender.haha.Encoding=UTF-8
-
log4j.xml
配置<appender name="A1" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="all.log" /> <!-- 一定要加上这行编码配置 --> <param name="Encoding" value="UTF-8" /> ...... </appender>
-
log4j2.xml
配置<?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG"> <Appenders> <!--这个输出控制台的配置--> <Console name="Console" target="SYSTEM_OUT" follow="true"> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY" /> <!-- 输出日志的格式 --> <PatternLayout charset="GBK" pattern="%m%n" /> </Console> <!-- RollingFile 相关配置 --> <RollingFile name="rolling_file" fileName="${logDir}/dust-server.log" filePattern="${logDir}/dust-server_%d{yyyy-MM-dd}.log"> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY" /> <!-- 输出日志的格式 --> <PatternLayout charset="UTF-8" pattern="%m%n" /> </RollingFile> </Appenders> <Loggers> <Root level="all"> <AppenderRef ref="Console"/> <AppenderRef ref="rolling_file"/> </Root> </Loggers> </Configuration>