【bug】: springboot项目打包成.war执行时,下载文件内容中文乱码

先说结论:
java -jar运行时的编码方式和该下载文件的编码方式不一致导致的

1. 场景/问题

客户端 下载excel文件时,下载下来的文件中文乱码,且表头和数据也是错位的
在这里插入图片描述

2. 排查

肯定是文件编码类型冲突导致的。

  • 项目运行所在电脑是window,默认的系统编码是GBK。程序运行(java -jar)时并没有指定JVM输出字符串的编码格式,所以就是GBK。

  • 项目中文件下载的代码
    在这里插入图片描述
    可以发现,在写文件的过程中,指定了被写入的文件的编码格式是UTF8.

  • 所以,项目运行后,当前端执行下载命令时,触发该条语句就会创建一个UTF编码格式的文件,但是整个程序是以GBK编码格式输出字符串的,整个文件返回也是要遵从GBK编/解码。所以相当于用GBK去解码UTF8编码的文件,当然就会发生中文乱码异常

3. 解决

既然你创建文件是UTF8,那不如指定运行时的JVM输出编码也是UTF-8
java -jar -Dfile.encoding=UTF8 ROOT.war

但是

这时候发现控制台输出日志和日志文件中的日志又是中文乱码了。
因为window的cmd默认编码格式是GBK,你输出的字符串编码是UTF8,当然控制台显示的时候就会乱码了。
解决方法:
修改cmd的编码格式 :chcp 65001

-Dfile.encoding=UTF-8

从file,可以推断和文件有关。
使用java.io中的方法时,会使用file.encoding取得具体的编码方式。
所以。-Dfile.encoding就是为了改变jdk处理文件【程序中使用OutPutStreamWriter】的默认字符编码,
如果不手动设定,默认的file.encoding是当前操作系统的默认编码,也就是GBK

chcp

chcp
在这里插入图片描述
cmd中,chcp返回是当前操作系统的默认编码格式的号码
963对应GBK(window默认的)
65001对应UTF-8

MORE

1. window记事本的默认编码格式

修改记事本的编码格式
window中记事本默认的编码格式是UTF-8
在这里插入图片描述
另存为修改编码格式
在这里插入图片描述

2. cmd的type命令

type
类似于linux的cat,将一个文件转到屏幕

一、编译过程

测试代码:hello.java

1. 控制台打开文件

public class Hello {
    public static void main(String[] args) {
        System.out.println(System.getProperty("file.encoding"));
        System.out.println("你好,中国");
    }
}

window上,用sublime text保存文件

  1. save with encoding utf-8
    在这里插入图片描述
    输出乱码,hello.java 【UTF8】 和 cmd【GBK】冲突。这是因为window的cmd默认编码是GBK,你以UTF-8编码格式保存的文件,用GBK解码UTF编码的文件肯定会出现异常的
    (控制台展示文件,也可以看成是对源文件的一个解码过程)
  2. save with encoding GBK
    在这里插入图片描述

2. 编译源文件

编译,肯定要先读再编译啊,关键是【不能正确的读】是乱码的一个原因
导致乱码的不是Java源码编译器的“编码”(以UTF-8保存的、)的过程,而是“解码”(读入.java源码内容)的过程
在这里插入图片描述
例:

  • BK保存的文件:
    在这里插入图片描述
    成功编译

  • UTF保存的文件:
    在这里插入图片描述
    对于javaCompiler,如果在不指定源文件编码类型的情况下,将会用系统默认编码去解码源文件。
    这里,就相当于,用javaCompiler用GBK去解码UTF编码的源文件了,当然会产生乱码。

-encoding UTF8

所以,需要指定源文件的编码类型,这里用-encoding UTF8 指定。这样javaCompiler才知道用什么解码类型去解码源文件
在这里插入图片描述

二、执行过程

也就是执行class文件的过程
class文件的编码格式都是固定的,UTF8。javaCompiler解码.java后会编译成UTF8格式的class文件

1. 执行文件

GBK源文件:
在这里插入图片描述

为啥这两个都是正常的呢?

2. 乱码

一直编译正确的情况下,为什么运行的时候还会产生中文乱码?
那原因肯定是在JVM 从.class文件读取这个字符串字节流并构建String对象的时候采用了错误的字符编码来构建字节流。
进而导致从JVM输出字符串的字节流到我们控制台的时候,出现乱码

所以,如果确定是运行时的乱码,那就是控制台的问题了。默认是用控制台的编码方式输出字符串的。
(1)改变控制台运行环境
(2)决定这个文件,以何种方式输出字符串。-Dfile.encoding
在这里插入图片描述
在这里插入图片描述

三、idea中的编码配置

1. 控制台乱码

源码: 右下角有这个文件的编码格式,UTF8
在这里插入图片描述
发现输出GBK,且中文乱码了。这已经是运行时的结果了。

查看class文件,发现在编译后的class文件中就已经乱码了,是编译时的乱码。
class文件,这时候发现右下角是GBK,应该是java compile解码类型
在这里插入图片描述

所以,问题就出在javaCompile解码的方式不对了,全局设置编译器的解码方式,实际
在这里插入图片描述
注意,修改之后,需要重启idea才能生效
这时候可以再去运行,可以看到
在这里插入图片描述
class文件中是正常的中文

2. maven打包编译编码

如果是maven打包文件,有

<properties>
 	<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>


<build>
        <finalName>ROOT</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>

                </configuration>
            </plugin>
		</plugins>
</build>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值