在开发的时候,经常会碰到一个问题,本地无乱码而部署到服务器上后服务器出现了乱码,在此记录下我的解决方法:
一直以来我都有一个误区,一直认为“字节无编码,字符串有编码”,而事实刚好相反,事实上是“字符串无编码,字节有编码”。
不同编码,中文和英文字符所占字节不同,UTF_8是一种变长的编码方式,对英文字符使用单字节编码,对中文字符使用三个字节来编码;而GBK是国家制定的汉字编码标准,使用双子节进行编码,所以不同的编码,将字节转成字符的方式不同。而Java 字符串是由一串字符数组char[]组成,字符是由字节组成,一个中文和一个英文字母都是占一个字符,Java代码在显示String时,需要将字节根据编码(UTF或GBK或其他)转成字符,然后组成字符数组char[]显示,这就是说明了“字符串无编码,字节有编码”。
所以,我们在接收消息时进行编码转码时,需要将接收的消息以该消息的编码方式解码成字符串,然后将字符串以我们需要编码进行编码,即:
byte[] gbkByteArr = 字节流接收消息,获得接收消息字节流数组;
String gbkMsg = new String(gbkByteArr ,"GBK") //用消息的编码进行解码,假如消息编码方式是GBK,此处就用GBK解码; 到此得到的字符串应该就是无乱码的字符串
往往出现乱码不是解码出错,而是认为在得到gbkMsg后无乱码后,Java编码解码就结束了,其实这只是第一步,我们仍需对gbkMsg进行编码,将其转成我们需要的编码。具体如下:
byte[] utf8ByteArr = gbkMsg .getBytes(UTF_8); //如果需要的消息UTF_8,在此将gbkMsg 转成UTF_8的字节数组,在此一定要指定编码方式,不然Java会按JVM设置的编码进行编码,如果JVM未指定编码,会根据当前操作系统的编码指定,不同的服务器上虚拟机JVM或操作系统有可能设置的编码不同,就造成了不同服务器有的出现乱码,有的正常。我就是由于此步骤未设置编码,造成了本地服务器正常,而线上服务器乱码。
Strign utf8Msg = new String(bytes_emt , UTF_8); //获得以UTF_8编码的字节数组utf8ByteArr对应的字符串
总结:针对不同编码的转换(以GBK--转UTF_8为例)方式:
1、先将消息以字节流方式获取,获得字节数组byte[] gbkByteArr ;
2、将字节以“GBK”的方式解码,获得字符串gbkMsg
3、将字符串gbkMsg 以“UTF_8”的方式编码,获得编码是UTF_8的字节流byte[] utf8ByteArr
4、然后将字节流utf8ByteArr以UTF_8的方式转成字符串