在任何编程语言中,存取和操作字符串都是一个常见的操作。这一切的前提,就要先规定存储和读取字符的规则,这就是字符串的编码。
一、字符串的编码
英文的编码就是ASCII,中文常见的编码有GBK和UTF-8编码。由于GBK和UTF-8编码的前128位就是ASCII码,所以英文和半角符号基本上没有乱码的情况。
二、Java中的编码与解码
默认情况下,JVM在加载Class文件的时候,会根据Class文件本身的编码来读取文件中的中文,读取到的中文在JVM中都会转成Unicode编码(不考虑JDK6与Windows XP)——在这种情况下,你自己写的代码中出现的中文应该总是可以正常显示的。
众所周知,char类型本身不含编码信息,只是纯数字,存储和操作时都是操作的这个数字。我们可以将一种编码理解为一个数组,需要显示字符的时候才拿着char对应的值去编码数组中取下标对应的符号显示出来。String类的内容就是存在一个字符(char)数组中的,下面是JDK8.0中String类的定义:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
...
}
由于value数组是私有的,所以只有在调试模式下能看到它。除此以外,我们还可以使用String.getBytes()方法来取到它的值——但是,getBytes取到的未必是当前String中value数组中的值,还有可能是经过了编码转换后的值。
三、String.getBytes("encoding")
按照字面意思理解,这个函数应该是单纯的将String按照encoding编码分割为字节而已。但是,实际上它并不仅做了拆分,而且做了转换。困扰大多数初识Java的童鞋的问题应该就在转换这一步。
1. 如果encoding与字符串当前的编码一致:
那就直接分割为字节数组。
2. 如果encoding与字符串当前的编码不一致:
那就先按照原编码进行读取,然后按照编码映射规则将字符串转换为目标编码,然后分割为字节数组。
四、Java中对字符串进行转码
了解了以上内容,那么再处理乱码或者转码就变得胸有成竹了。不用管Java默认编码是什么、操作系统默认编码是什么,只需要getBytes一下即可:
String defaultString = "some 文本";
String gbkString = new String(defaultString.getBytes("GBK"), "GBK");//转成了GBK
String utf8String = new String(defaultString.getBytes("UTF-8"), "UTF-8");//转成了UTF-8
String utf8String = new String(gbkString.getBytes("UTF-8"), "UTF-8");//也可以转成UTF-8
如果你还是心存疑惑:转换的效果如何体现?那么可以试试下面的代码:
String x = "some 文本";
System.out.println("原始文本:"+x);
System.out.println("GBK编码:\n字节流:"+Arrays.toString(x.getBytes("GBK")));
System.out.println("长度:"+x.getBytes("GBK").length);
System.out.println("GBK解码:"+new String(x.getBytes("GBK"), "GBK"));
System.out.println("UTF-8解码:"+new String(x.getBytes("GBK"), "UTF-8"));
System.out.println("UTF-8编码:\n字节流:"+Arrays.toString(x.getBytes("UTF-8")));
System.out.println("长度:"+x.getBytes("UTF-8").length);
System.out.println("UTF-8解码:"+new String(x.getBytes("UTF-8"), "UTF-8"));
System.out.println("GBK解码:"+new String(x.getBytes("UTF-8"), "GBK"));
如果可以理解以上输出内容,那么恭喜,你已经掌握了Java中的编码:)
特别鸣谢:张强、刘舰阳、白高阳、张峰的帮助与提点。
Comments | NOTHING