Java加载路径中文乱码(GBK还是UTF-8)

首先分享一个up的视频,深入浅出,有空没空都看看,相信会有所收获。24.2.22补充。

你懂乱码吗?锟斤拷烫烫烫(详解ASCII、Unicode、UTF-32、UTF-8编码)_哔哩哔哩_bilibili

----------------------------------------------------------------------------------------------------------

乱码的本质就是:读取二进制的时候采用的编码和最初将字符转换成二进制时的编码不一致。

使用GBK进行编码,每1个汉字占2个字节,而使用UTF-8进行编码则每个汉字占3个字节(常用汉字占3个字节,有的稀有汉字会占四个字节),更精确的说是一种变长编码的特殊方式。

先说解决方案

遇到以下几种格式的乱码可以尝试一下

1、常见路径乱码是这样的

  • file:/G:/%e8%af%be%e7%a8%8b/%e7%ac%ac%e5%9b%9b%e9%98%b6%e6%ae%e4%b8%bb%e6%b5%81%e6%a1%86%e6%9e%b601/%e4%b8%bb%e6%b5%81%e6%a1%86%e6%9e%b6/%e4%b8%bb%e6%b5%81%e6%a1%86%e6%9e%b6/Spring/%e4%bb%a3%e7%a0%81/myspring/target/classes/com/...

显示的数据实际上就是字符的UTF-8的值,每个字节前加上%

URL resource = classLoader.getResource(path);
path = URLDecoder.decode(resource.getFile(), "UTF-8")

String newPath = new String(path.getBytes("UTF-8"),"UTF-8"); //这个方法不好用了

2、有时候乱码是这样的

  • /G:/璇剧▼/绗洓闃舵-涓绘祦妗嗘灦01/涓绘祦妗嗘灦/涓绘祦妗嗘灦/Spring/浠g爜/myspring/target/classes/com/...

这样一般是编码采用的UTF-8,解码采用的GBK,getBytes就可以解决

String Gbk2UtfString = new String(utf2GbkString.getBytes("GBK"),"UTF-8");

3、有时候是这样的

  • ��������й��

这样一般是编码采用的GBK,解码采用的UTF-8,解码失败造成的。按道理来讲转回去就行了。

String gbk2Utf2GbkString = new String(gbk2UtfString.getBytes("UTF-8"), "GBK");

这里有可能是正确的。但是再转回GBK也可能会出现上面一种情况(一堆看不懂的字)

这里的问题不太好解决,先说结论:

向上追溯,找出编解码的代码,修改成使用同一种编码方式。

4、补充:还有可能是这样的

  • \u4e2d\u56fd

这是java内部采用的unicode编码,一般只会在后台的配置文件中看到。

看看原理(没兴趣可以不看)

getBytes()

getBytes() 是Java编程语言中将一个字符串转化为一个字节数组byte[]的方法。

系统存储字符数据时(字符串就是字符数据),会先进行查表,然后将查询的结果写入设备,读取时也是先查表,把查到的内容打印到显示设备上,getBytes()是使用默认的字符集进行转换,getBytes(“utf-8”)是使用UTF-8编码表进行转换。

getBytes()方法属于String类,其用法如下:

public byte[] getBytes()
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException

第一个getBytes()方法:该方法将使用平台默认的字符编码方式,将字符串转换为字节数组。返回一个byte数组,其中每个字节都表示字符串中相应位置的字符。

第二个getBytes()方法:该方法需要传入一个字符编码方式charsetName作为参数,将字符串转换为字节数组。可能会抛出UnsupportedEncodingException异常,需要进行异常处理。
 

这里返回的都是byte数组,所以我们通常和new String搭配使用

String newPath = new String(path.getBytes("UTF-8"),"UTF-8");

//现在流行这么写,本质是一样的
String newPath = new String(path.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)

我们看到,将带有中文路径的path以UTF-8编码转换成byte数组(byte数组其实就相当于二进制序列了,此过程即编码),再以UTF-8编码和byte数组创建新的字符串(此过程即以UTF-8编码去解码byte数组,得到字符串)。

URLDecoder 的decoder方法

因为ClassLoader 的getResource 方法使用了utf-8 对路径信息进行了编码,当路径中存在中文和空格时,他会对这些字符进行转换,这样有时会出现乱码,所以在可以使用URLDecoder 的decoder方法进行解码,以便得到原始的中文及空格路径。

 这里有URLDecoder 的decoder方法源码解析:

解决通过this.class.getResource()得到的URL中乱码的问题及源码解析_getresource url处理_独行客-编码爱好者的博客-CSDN博客

UTF-8(解释上面第三种乱码)

正是由于UTF-8采用一种特别的变长编码方式,即将常用的字符编码成较短的序列,而不常用的字符用较长的序列表示,这样让编码占用更少存储空间的同时也保证了对庞大字符集的支持。

但是有些序列是不可能出现在UTF-8编码中的

由于GBK编码出了不可能出现在UTF-8编码中出现的序列,所以当我们试图用UTF-8去解码时,经常会遇到这种不可能序列,对于这种不可能序列,UTF-8把它们转换成某种不可言喻的字符“�”,当这种不可言喻的字符再次以UTF-8进行编码时,他们已经无法回到最初的样子了,因为那些是UTF-8编码不可能编出的序列。然后这个神秘字符再转换成GBK编码时就变成了“锟斤拷”。

当然,还有很多其他的巧合,可能正好碰到UTF-8中存在的序列,甚至原本不是一个字符的字节,可能是某个字的第二个字节和下一个字的两个字节,正好被识别成一个UTF-8序列,于是解码出一个汉字,当然这些在我们看来都是乱码。

关于IDEA中Java代码在控制台输出的乱码现象的解决方案。_java控制台乱码_何少杰666的博客-CSDN博客

这篇文章的大概意思是原先不知道什么编码,用UTF-8解码失败,出现未知字符。然后他用GBK解码成功了。后来出现问题又改成UTF-8,又出现乱码,又改回GBK,这一套操作挺抽象的,不太清楚原理。

所以:以非UTF-8编码(例如GBK)编码出的字节数组,一旦以UTF-8进行解码,很可能出现UTF-8解析不了的情况。

建议:

1、编程过程中尽量使用英文,尤其是路径,不要有中文,更不要有奇奇怪怪的字符,空格也尽量不要出现。

2、尽量编程的时候就用UTF-8编码,往别的编码方式上转好转,转回来不好转,UTF-8也可以很好的解析中文。

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值