A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© bird_not_fat 中级黑马   /  2013-10-12 18:04  /  1514 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

utf-8中的中文字符占三个字节,gbk中的中文字符占2个字节。如果用gbk编码,utf-8解码的话,比如说“你好”,用gbk编码编出来的字节数组为4个字节,再用utf -8查表解码解析出来的为什么是"???"三个问号,而不是1个或者2个问号。

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1

查看全部评分

11 个回复

倒序浏览
  1. public class Test3 {

  2.         public static void main(String[] args) throws IOException {
  3.                 byte[] buf = "你好".getBytes("gbk");
  4.                 for(byte temp:buf){
  5.                         System.out.println(temp);
  6.                 }
  7.                
  8.                 byte[] buf2 = new byte[]{-60,-29,-70,-61,0,0};
  9.                 String str = new String(buf,"utf-8");
  10.                 System.out.println(str);
  11.                
  12.                 String str1 = new String(buf2, 0, 2, "utf-8");
  13.                 String str2 = new String(buf2, 3, 2, "utf-8");
  14.                 System.out.println(str1 + str2);
  15.         }
  16. }
复制代码
"你好"用gbk编码是-60,-29,-70,-61 四个字节,而你用utf-8解码却是以三个字节来解码一个字,所以utf-8解码-60,-29,-70时得出的是??而不是?,上面代码运行可看结果,而剩下的一个-61不足3个字节,会以-61,0,0来自动补0满足3个字节,而utf-8解码-61,0,0是只有?,所以加起来就是???,而不是?或者??。纯手打,望加分 = =

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1

查看全部评分

回复 使用道具 举报
当用gbk进行字符串的编码时,因为每一个汉字对应的是两个字节,即以"你好"为例就是4个字节,而utf-8中的汉字一般对应3个字节,即就是6个字节,所以当用utf-8进行解码时便将4分解成了3和1分别去utf-8表中进行匹配,当找不到对应信息时便为视为未知信息,就会出现??,不可能出现???的。谢谢!
回复 使用道具 举报
Jam-l 发表于 2013-10-12 18:34
"你好"用gbk编码是-60,-29,-70,-61 四个字节,而你用utf-8解码却是以三个字节来解码一个字,所以utf-8解码- ...
  1. public class CodeDemo3 {
  2.         public static void main(String[] args) {
  3.                 String hello = "大家";
  4.                 byte[] bt = null;
  5.                 try {
  6.                         bt = hello.getBytes("gbk");
  7.                 } catch (UnsupportedEncodingException e) {
  8.                         e.printStackTrace();
  9.                 }
  10.                 for(byte b:bt){
  11.                         //255的2进制形式为 00000000-00000000-00000000-11111111
  12. //                        System.out.println(Integer.toBinaryString(255));
  13.                         //位运算& 得到:11000100 11100011 10111010 11000011
  14.                         System.out.println(Integer.toBinaryString(b & 255));
  15.                 }
  16.                 String getHello = null;
  17.                 try {
  18.                         getHello = new String(bt,"utf-8");
  19.                 } catch (UnsupportedEncodingException e) {
  20.                         e.printStackTrace();
  21.                 }
  22.                 System.out.println(getHello);
  23.         }
  24. }
复制代码
可是如果把你好,改成“大家”,得到的就是"??",所以我觉得可能不是这个原因。。亲再帮我想想

回复 使用道具 举报
hello菜菜 发表于 2013-10-12 18:42
当用gbk进行字符串的编码时,因为每一个汉字对应的是两个字节,即以"你好"为例就是4个字节,而utf-8中的汉 ...

亲,其实不是这样的,
UTF-8对所有字节都加了一个标识头信息,它按照这个标识头来告诉自己查表时到底一次读取几个字节。
当字节头为0的时候一次读取一个字节。
当字节头为(第一个字节头)1110-(第二个字节头)10-(第三个字节头)10的时候一次读取三个字节。因此一次查询三个字节这种说法是站不住的。
再帮我想想啊,嘿嘿
回复 使用道具 举报
hello菜菜 发表于 2013-10-12 18:42
当用gbk进行字符串的编码时,因为每一个汉字对应的是两个字节,即以"你好"为例就是4个字节,而utf-8中的汉 ...

亲,其实不是这样的,
UTF-8对所有字节都加了一个标识头信息,它按照这个标识头来告诉自己查表时到底一次读取几个字节。
当字节头为0的时候一次读取一个字节。
当字节头为(第一个字节头)1110-(第二个字节头)10-(第三个字节头)10的时候一次读取三个字节。因此一次查询三个字节这种说法是站不住的。
再帮我想想啊,嘿嘿
回复 使用道具 举报
Jam-l 中级黑马 2013-10-12 19:21:49
7#
bird_not_fat 发表于 2013-10-12 19:12
可是如果把你好,改成“大家”,得到的就是"??",所以我觉得可能不是这个原因。。亲再帮我想想

...
  1. public class Test3 {

  2.         public static void main(String[] args) throws IOException {
  3.                 byte[] buf = "大家".getBytes("gbk");
  4.                 for(byte temp:buf){
  5.                         System.out.println(temp);
  6.                 }
  7.                
  8.                 byte[] buf2 = new byte[]{-76,-13,-68,-46};
  9.                 String str = new String(buf,"utf-8");
  10.                 System.out.println(str);
  11.                
  12.                 String str1 = new String(buf2, 0, 2, "utf-8");
  13.                 String str2 = new String(buf2, 3, 0, "utf-8");
  14.                 System.out.println(str1 + str2);
  15.         }
  16. }
复制代码
我弄错了,它是不会自动补0的,大家是-76,-13,-68,-46,而-76,-13,-68的utf-8编码是??,,-46的utf-8编码是null,所以加起来是??,不信你试试
回复 使用道具 举报
bird_not_fat 发表于 2013-10-12 19:15
亲,其实不是这样的,
UTF-8对所有字节都加了一个标识头信息,它按照这个标识头来告诉自己查表时到底一次 ...

亲,我看到你的代码中将输入的汉字用gbk编码后,获取时又和255进行了与运算,这样就将原来的值改变了,当再次通过utf-8进行解码时,就会按照标记号进行1位、2位、或是3位的查找,但是由于前后的编码、解码参照表不同,所以肯定会出现?,只不过出现次数不规律而已。
回复 使用道具 举报
hello菜菜 发表于 2013-10-12 19:30
亲,我看到你的代码中将输入的汉字用gbk编码后,获取时又和255进行了与运算,这样就将原来的值改变了,当 ...

恩啊,嘿嘿,我再想想~~3q~
回复 使用道具 举报
Jam-l 发表于 2013-10-12 19:21
我弄错了,它是不会自动补0的,大家是-76,-13,-68,-46,而-76,-13,-68的utf-8编码是??,,-46的utf-8编 ...
  1. import java.io.UnsupportedEncodingException;

  2. public class CodeDemo3 {
  3.         public static void main(String[] args) {
  4.                 String hello = "大家";
  5.                 byte[] bt = null;
  6.                 try {
  7.                         bt = hello.getBytes("gbk");
  8.                 } catch (UnsupportedEncodingException e) {
  9.                         e.printStackTrace();
  10.                 }
  11.                 for(byte b:bt){
  12.                         //255的2进制形式为 00000000-00000000-00000000-11111111
  13. //                        System.out.println(Integer.toBinaryString(255));
  14.                         //位运算& 得到:11000100 11100011 10111010 11000011
  15.                         System.out.println(Integer.toBinaryString(b & 255));
  16.                 }
  17.                 String getHello = null;
  18.                 String getHelloPart1 = null;
  19.                 String getHelloPart2 = null;
  20.                 String getHelloPart3 = null;
  21.                 try {
  22.                         getHello = new String(bt,"utf-8");
  23.                         getHelloPart1 = new String(bt,0,1,"utf-8");
  24.                         getHelloPart2 = new String(bt,1,2,"utf-8");
  25.                         getHelloPart3 = new String(bt,2,2,"utf-8");
  26.                 } catch (UnsupportedEncodingException e) {
  27.                         e.printStackTrace();
  28.                 }
  29.                 System.out.println(getHello);
  30.                 System.out.println(getHelloPart1);
  31.                 System.out.println(getHelloPart2);
  32.                 System.out.println(getHelloPart3);
  33.         }
  34. }
复制代码
不能这么试啊亲..我试了试,
10110100
11110011
10111100
11010010
??
?
?
??
结果发现这样拼字节的方法不好使啊。。各种?出来了。。
回复 使用道具 举报
To 金牌黑马 2013-10-13 13:51:36
11#
楼主你好,如果问题已解决请将帖子状态修改为提问结束,如果未解决请继续提问,谢谢合作
回复 使用道具 举报
To 金牌黑马 2013-10-14 09:24:47
12#
楼主你好,如果问题已解决请将帖子状态修改为提问结束,如果未解决请继续提问,谢谢合作
如果不会修改请看解释帖:http://bbs.itheima.com/thread-89313-1-1.html
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马