1700442910
1700442911
步骤1 创建Client.java文件。
1700442912
1700442913
该文件的默认编码GBK(如果使用Eclipse,则可以在属性查看到)。
1700442914
1700442915
步骤2 编写代码(如上)。
1700442916
1700442917
步骤3 保存,并使用javac编译。
1700442918
1700442919
注意我们没有使用“javac-encoding GBK Client.java”显式声明Java的编码格式,javac会自动按照操作系统的编码(GBK)读取Client.java文件,然后将其编译成.class文件。
1700442920
1700442921
步骤4 生成.class文件。
1700442922
1700442923
编译结束,生成.class文件,并保存到硬盘上。此时.class文件使用的是UTF-8格式编码的UNICODE字符集,可以通过javap命令阅读class文件。其中“汉字”变量也已经由GBK编码转变成UNICODE格式了。
1700442924
1700442925
步骤5 运行main方法,提取“汉字”的字节数组。
1700442926
1700442927
“汉字”原本是按照UTF-8格式保存的,要再提取出来当然没有任何问题了。
1700442928
1700442929
步骤6 重组字符串。
1700442930
1700442931
读取操作系统的编码格式(GBK),然后重新编码变量b的所有字节。问题就在这里产生了:因为UNICODE的存储格式是两个字节表示一个字符(注意这里是指UCS-2标准),虽然GBK也是2个字节表示一个字符,但两者之间没有影射关系,要想做转换只能读取映射表,不能实现自动转换—于是JVM就按照默认的编码格式(GBK)读取了UNICODE的两个字节。
1700442932
1700442933
步骤7 输出乱码,程序运行结束。
1700442934
1700442935
问题清楚了,解决方案也随之产生,方案有两个。
1700442936
1700442937
步骤8 修改代码。
1700442938
1700442939
明确指定编码即可,代码如下:
1700442940
1700442941
System.out.println(new String(b,“UTF-8”));
1700442942
1700442943
步骤9 修改操作系统的编码方式。
1700442944
1700442945
各个操作系统的修改方式不同,不再赘述。
1700442946
1700442947
我们可以把从字符串读取字节的过程看作是数据传输的需要(比如网络、存储),而重组字符串则是业务逻辑的需求,这样就可使乱码现场重现:通过JDBC读取的字节数组是GBK的,而业务逻辑编码时采用的是UTF-8,于是乱码产生了。对于此类问题,最好的解决办法就是使用统一的编码格式,要么都用GBK;要么都用UTF-8,各个组件、接口、逻辑层都用UTF-8,拒绝独树一帜的情况。
1700442948
1700442949
问题解释清楚了,我们再来看以下代码:
1700442950
1700442951
public class Client{
1700442952
1700442953
public static void main(String[]args)throws Exception{
1700442954
1700442955
String str=“汉字”;
1700442956
1700442957
//读取字节
1700442958
1700442959
byte[]b=str.getBytes(“GB2312”);
[
上一页 ]
[ :1.70044291e+09 ]
[
下一页 ]