GBK与UTF-8 转换乱码详解(转)
getBytes 的功能是将字符转换成字节数组, gbk.getBytes("GB2312") 用GB2312翻译成字节数组, new String(gbk.getBytes("GB2312"),"UTF-8"); 把用GB2312翻译成字节数组,再用UTF-8翻译成字符串。 兄弟你想下,这里有没有问题? 这就是乱码的原因。 下面再分析下你具体的问题: GB23121 -》ISO-8859 两个字节到一个字节 反过来,再一个字节到两个字节,不会有问题, 因为翻译时,个数不会多也不会少。 再看GBK -》UTF-8 两个字节翻译的字节数组现在要用三个字节翻译 就是说你 4个字节给人家 人家是一次要三个,出现什么情况? 拿了三个 剩下一个不够,人家就自己去添加。 你再翻译回来的时候就是 6个字节了,也说明为什么变成了三个字提供一个转换方法:public byte[] gbk2utf8(String chenese){ char c[] = chenese.toCharArray(); byte [] fullByte =new byte[3*c.length]; for(int i=0; i<c.length; i++){ int m = (int)c[i]; String word = Integer.toBinaryString(m); // System.out.println(word); StringBuffer sb = new StringBuffer(); int len = 16 - word.length(); //补零 for(int j=0; j<len; j++){ sb.append("0"); } sb.append(word); sb.insert(0, "1110"); sb.insert(8, "10"); sb.insert(16, "10"); // System.out.println(sb.toString()); String s1 = sb.substring(0, 8); String s2 = sb.substring(8, 16); String s3 = sb.substring(16); byte b0 = Integer.valueOf(s1, 2).byteValue(); byte b1 = Integer.valueOf(s2, 2).byteValue(); byte b2 = Integer.valueOf(s3, 2).byteValue(); byte[] bf = new byte[3]; bf[0] = b0; fullByte[i*3] = bf[0]; bf[1] = b1; fullByte[i*3+1] = bf[1]; bf[2] = b2; fullByte[i*3+2] = bf[2]; } return fullByte; }
?应该编码转换的时候丢失了字节,你没有发现你输入的是偶数个字的时候正常,奇数个的时候乱码,具体的字码长度我也不是很了解
String str1 = new String(str.getBytes("UTF-8"),"GBK");
System.out.println(str1.length());
String str2 = new String(str1.getBytes("GBK"),"UTF-8");
System.out.println(str2.length());); 打印出来的字符串长度就不一样的
UTF8每个汉字占用3个字节,这样在某些地方文字个数的计算就和GBK编码的不一样,UTF-8使用可变长度字节来储存 Unicode字符,例如ASCII字母继续使用1字节储存,重音文字、希腊字母或西里尔字母等使用2字节来储存,而常用的汉字就要使用3字节。辅助平面字符则使用4字节。 GB 18030标准采用单字节、双字节和四字节三种方式对字符编码。单字节部分使用0×00至0×7F码(对应于ASCII码的相应码)。双字节部分,首字节码从0×81至0×FE,尾字节码位分别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE,第二、四个字节编码码位均为0×30至0×39。
按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。
?
载自:http://jlins.iteye.com/blog/574670