Java GetBytes 编码方式
在JAVA源文件-->JAVAC-->Class-->Java-->getBytes()-->new String()-->显示的过程中,每一步都有编码的转换过程,这个过程总是存在的,只是有的时候用默认的参数进行。
1. JAVAC是以系统默认编码读入源文件,然后按UNICODE进行编码的。可以通过指定编码方式改变Javac读入源文件的编码方式。
- javac -encoding GBK Test.java
2. 在JAVA运行的时候,JAVA也是采用UNICODE编码的,并且默认输入和输出的都是操作系统的默认编码。
也就是说在new String(bytes[,encode])中,系统认为输入的是编码为encode的字节流,换句话说,如果按encode来翻译bytes才能得到正确的结果,这个结果最后要在JAVA中保存,它还是要从这个encode转换成Unicode,也就是说有bytes-->encode字符-->Unicode字符的转换;而在String.getBytes([encode])中,系统要做一个Unicode字符-->encode字符-->bytes的转换。
3. Java中的编码支持
Java是支持多国编码的,在Java中,字符都是以Unicode进行存储的,比如,“你”字的Unicode编码是“4f60”,我们可以通过下面的实验代码来验证:
- class TestCharset {
- public static void main(String[] args)
- {
- char c = '你';
- int i = c;
- System.out.println(c);
- System.out.println(i);
- }
- }
不管你在任何平台上执行,都会有相同的输出:20320,20320就是Unicode “4f60”的整数值。其实,你可以反编译上面的类,可以发现在生成的.class文件中字符“你”(或者其它任何中文字串)本身就是以Unicode编码进行存储的:char c = '\u4F60';
4. 为了避免这种问题,建议大家都在编码中使用String.getBytes(String charset)方法。
- class TestCharset {
- public static void main(String[] args) {
- new TestCharset().execute();
- }
- private void execute() {
- String s = "Hello!你好!";
- byte[] bytesISO8859 =null;
- byte[] bytesGBK = null;
- try
- {
- bytesISO8859 =
- s.getBytes("iso-8859-1");
- bytesGBK = s.getBytes("GBK");
- }
- catch
- (java.io.UnsupportedEncodingException e)
- {
- e.printStackTrace();
- }
- System.out.println
- ("--------------\n 8859 bytes:");
- System.out.println("bytes is: " + arrayToString(bytesISO8859));
- System.out.println("hex format is:"
- + encodeHex(bytesISO8859));
- System.out.println();
- System.out.println
- ("--------------\n GBK bytes:");
- System.out.println("bytes is:" + arrayToString(bytesGBK));
- System.out.println("hex format is:" + encodeHex(bytesGBK));
- }
- public static final String
- encodeHex (byte[] bytes)
- {
- StringBuffer buff =
- new StringBuffer(bytes.length * 2);
- String b;
- for (int i=0; i<bytes.length ; i++)
- {
- b = Integer.toHexString(bytes[i]);
- // byte是两个字节的,而上面的Integer.toHexString会把字节扩展为4个字节
- buff.append(b.length() > 2 ? b.substring(6,8) : b);
- buff.append(" ");
- }
- return buff.toString();
- }
- public static final String arrayToString(byte[] bytes) {
- StringBuffer buff = new StringBuffer();
- for (int i = 0; i < bytes.length; i++) {
- buff.append(bytes[i] + " ");
- }
- return buff.toString();
- }
- }
执行上面程序将打印出:
-------------- 8859 bytes: bytes is: 72 101 108 108 111 33 63 63 63 hex format is:48 65 6c 6c 6f 21 3f 3f 3f -------------- GBK bytes: bytes is: 72 101 108 108 111 33 -60 -29 -70 -61 -93 -95 hex format is:48 65 6c 6c 6f 21 c4 e3 ba c3 a3 a1 |
可见,在s中提取的8859-1格式的字节数组长度为9,中文字符都变成了“63”,ASCII码为63的是“?”,一些国外的程序在国内中文环境下运行时,经常出现乱码,上面布满了“?”,就是因为编码没有进行正确处理的结果。