前言
从长沙辞职跑到深圳,找房子找工作适应新的工作环境超级忙。之前一直没时间好好写博客,今天难得有空就上来写点东西吧!
都9102年了,没想到还能有那么多乱码问题。之前的工作基本上前后端统一编码就完事了;话不多说,既然遇到了就干脆搞搞明白吧!
实践出真知
网上很多关于乱码还原的解决办法,都是很片面甚至是误导性的。逆向转码是提到最多的,如下:
假定errStr是原本为gbk编码格式的字符串,但是使用utf-8进行解码从而形成了乱码。错误示范,并不能还原乱码
String str = new String(errStr.getBytes(StandardCharsets.UTF_8), "GBK");
逆向转码乍一看有道理,但真的经得起推敲吗?
实验一
假定乱码场景为:原本为gbk编码的字符串错误的使用了utf-8进行解码形成了乱码。现需要把这个乱码进行还原
按照网上很多人说的乱码还原的解决办法,即逆向转码就能解决。事实真的如此吗?
public static void main(String[] args) throws UnsupportedEncodingException {
String unicodeStr = "这是一串原本为GBK编码格式的字符串";
// gbks 为GBK编码格式
byte[] gbks = unicodeStr.getBytes("GBK");
// 解码验证 GBK解码方式不乱码而UTF8乱码则说明是GBK
String errStr = new String(gbks, StandardCharsets.UTF_8);
System.out.println(errStr);
String rightStr = new String(gbks, "GBK");
System.out.println(rightStr);
// 将原本为GBK编码格式 的乱码字符串 还原
// 乱码字符串进行还原
byte[] errBytes = errStr.getBytes(StandardCharsets.UTF_8);
String str = new String(errStr.getBytes(StandardCharsets.UTF_8), "GBK");
System.out.println(str);
}
控制台输出:
很显然一串原本为GBK编码格式的当使用了utf8解码而形成了乱码。当使用逆向转码试图还原乱码时形成了新的乱码。
事实上如果乱码中出现了问号,则表示这部分已经丢失了,是没有办法还原了的。即这串乱码是不可逆的。
实验二
假定乱码场景为:原本为utf8编码的字符串错误的使用了gbk进行解码形成了乱码。现需要把这个乱码进行还原
public static void main(String[] args) throws UnsupportedEncodingException {
String unicodeStr = "这是一串原本为UTF-8编码格式的字符串";
// gbks 为GBK编码格式
byte[] utf8s = unicodeStr.getBytes(StandardCharsets.UTF_8);
// 解码验证 utf8解码方式不乱码而gbk乱码则说明是utf8
String rightStr = new String(utf8s, StandardCharsets.UTF_8);
System.out.println(rightStr);
String errStr = new String(utf8s, "GBK");
System.out.println(errStr);
// 将原本为utf8编码格式 的乱码字符串 还原
// 乱码字符串进行还原
byte[] gbks = errStr.getBytes("GBK");
String str = new String(errStr.getBytes("GBK"), StandardCharsets.UTF_8);
System.out.println(str);
}
控制台输出:
当原本为utf8的字符串错误的使用了gbk解码后形成的乱码。经过逆向转码,是可以部分还原的,但是依然不能百分百还原!
最后
有很多一知半解的去解答别人关于乱码还原问题的解决方案时,简直就是误人子弟,乱码问题的关键在于从源头抓起,统一编码,使用正确的解码方式进行解码。
简言之:就是在形成乱码的那一步遏制,而不是乱码已经形成了再去想办法还原!
这篇写的很片面,下一篇我将分析一下编码解码以及乱码形成的具体原因,以及为什么原本为utf8的字符串形成的乱码部分可逆,部分不可逆。我目前也正在找资料,有知道的小伙伴不妨留言。。❀