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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 rslheima 于 2012-6-26 19:13 编辑

为什么同样是用GBK编码的“你好”两个字使用不同方法,都用utf-8解码,为什么一个是两个问号??,一个是三个问号???
  1. package io.ENCODE;

  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStreamWriter;
  7. import java.io.UnsupportedEncodingException;
  8. import java.util.Arrays;

  9. public class Encode {


  10.                 public static void main(String[] args) throws IOException {
  11.                         System.out.println("使用流操作转换“你好“");
  12.                         write();
  13.                         read();
  14.                         System.out.println("使用编码,解码--”你好“");
  15.                         encode();
  16.                 }
  17.                 //------------------使用gbk编码写入”你好“-------------------------
  18.                 public static void write() throws IOException{
  19.                         OutputStreamWriter osw=new OutputStreamWriter(
  20.                                         new FileOutputStream("C:\\Users\\Administrator\\Desktop\\utf.txt"),"gbk");
  21.                                 osw.write("你好");
  22.                                 osw.close();
  23.                 }
  24.                 //------------------使用utf-8编码读取“你好”-----------------------
  25.                         public static void read() throws IOException{
  26.                                 InputStreamReader irs=new InputStreamReader(new FileInputStream("C:\\Users\\Administrator\\Desktop\\utf.txt"),"utf-8");
  27.                                 char [] buf=new char[10];
  28.                                 int ch=0;
  29.                                  ch=irs.read(buf);
  30.                                 System.out.println(new String (buf,0,ch));
  31.                         }
  32.                 //-----------------使用字符编码,解码方式,-----------------------        
  33.                         public static void encode() throws UnsupportedEncodingException{
  34.                         String str="你好";
  35.                         //-----------------使用gbk编码----------
  36.                         byte[] b=str.getBytes("gbk");
  37.                         //System.out.println(Arrays.toString(b));
  38.                         //----------------使用utf-8解码-----------
  39.                         String s1=new String(b,"utf-8");
  40.                         System.out.println(s1);
  41.                         }
  42.         }
复制代码
结果:
使用流操作转换“你好“
??
使用编码,解码--”你好“
???

点评

呵呵,sorry,哥们刚却实没有细看代码。 是直接看结果与关键字 GBK与UTF-8的。 你这个问题,问的好。顶起,期待 高手讲解下。  发表于 2012-6-26 20:42

5 个回复

倒序浏览
本帖最后由 陈淑飞 于 2012-6-26 19:21 编辑

建议 楼主解决这个问题前,先在百度下 搜下 结果。
出现二个 ?? 问号与 三个??? 问题是为什么,先预猜下,然后带的问题去找答案。这样学习效率会提高很多。
呵呵,不过,也谢谢你提这个问题,让我也学习到了点。从这点来说,你对大家的贡献还是蛮大的。呵呵。
好了 废话说了一堆,说问题吧。

其它打印二个问号与三个问号的区别, 代码上没问题,只能说去找UTF-8与GBK编码有什么区别了。

UTF-8与GBK编码的区别

UTF-8:Unicode Transformation Format-8bit,是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码。

GBK是国家标准GB2312基础上扩容后兼容GB2312的标准。GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含全部中文字符,是国家编码,通用性比UTF8差。


通过这个,我们可以了解到原来:
UTF-8在给我们中文编码是采用了三个字节,而我们自己国家GBK编码对中文编码是采用了二个字节

欧了没?



回复 使用道具 举报

    import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.io.InputStreamReader;
        import java.io.OutputStreamWriter;
        import java.io.UnsupportedEncodingException;
        import java.util.Arrays;

        public class fdsdfs {


                        public static void main(String[] args) throws IOException {
                                System.out.println("使用流操作转换“你好“");
                                write();
                                read();
                                System.out.println("使用编码,解码--”你好“");
                                encode();
                        }
                        //------------------使用gbk编码写入”你好“-------------------------
                        public static void write() throws IOException{
                                OutputStreamWriter osw=new OutputStreamWriter(
                                                new FileOutputStream("C:\\Users\\Administrator\\Desktop\\utf.txt"),"gbk");
                                        osw.write("你好");
                                        osw.close();
                        }
                        //------------------使用utf-8编码读取“你好”-----------------------
                                public static void read() throws IOException{
                                        InputStreamReader irs=new InputStreamReader(new FileInputStream("C:\\Users\\Administrator\\Desktop\\utf.txt"),"gbk");//把utf-8改为gbk就可以了
                                        char [] buf=new char[10];
                                        int ch=0;
                                         ch=irs.read(buf);
                                        System.out.println(new String (buf,0,ch));
                                }
                        //-----------------使用字符编码,解码方式,-----------------------        
                                public static void encode() throws UnsupportedEncodingException{
                                String str="你好";
                                //-----------------使用gbk编码----------
                                byte[] b=str.getBytes("gbk");
                                //System.out.println(Arrays.toString(b));
                                //----------------使用utf-8解码-----------
                                String s1=new String(b,"gbk");//把utf-8改为gbk就可以了                                System.out.println(s1);
                                }
                }


结果:使用流操作转换“你好“
你好
使用编码,解码--”你好“
你好
回复 使用道具 举报
第一个问题:为什么是两个?号,你存的时候按gbk去存,那么你存的文件大小是4个字节,gbk当中两个字节表示一个汉字,假如存到硬盘的数据时 -12 -23 -34-56 ,那么前两个表示你 后两个表示好字,然而你读的时候你指定用utf-8去读取,utf-8是按三个字节来读的,那么就会取出 -12 -23 -34去utf-8表上查一查没有这个汉字 就给你返回一个?号,那么最后一个字节肯定也是找不到啊 就去未知字符去找 所以也是一个?号

第二个问题有点难度,需要查看dataInputStream下面有个utf-8修改表,我们可以通过一些方法获得你好这两个字的二进制数字,得出的结果是
11000100
11100011
10111010
11000011
当你用utf去解码的时候,因为第一个是110开头,按两个字节去读,但是第二个字节不是10 所以 第一个字节出现一个问号,然后接着读 第二个字节1110应该按三个字节去读
但是四个字节是110开头不是10开头所以又出现第二个问号,那最后一个就是一个问号了  希望能帮到你
回复 使用道具 举报
补充一点:第一个出现两个??的原因就是我上面说的 为什么呢  我给你加一段代码 你就知道了 在你read方法里加上System.out.println(a+"");然后你取的时候new String (buf,0,ch)) 这个ch的值是2 所以呢 就是按三个字节来处理的 最后一个字节 作为一个问号
回复 使用道具 举报
第一个问题:
使用流操作转换“你好“
??
因为你是用的使用gbk编码写入”你好“,在他的编码表中,每个中字占2个字节。
“你好”占了4个字节
然后你使用UTF-8读取“你好”,在他的编码表中,每个中字占3个字节。
当她读的时候,先拿了3个字节去查编码表,没有,就返回一个未知字符?
剩下1个,她又去查编码表,还没有,又返回一个未知字符?

第二个问题:
使用编码,解码--”你好“
???
用的GBK编码,还是4个字节
主要是UTF-8解码
因为UTF-8并不是每个字都是3个字节的,而是根据二进制位的开头来确定是占1个字节,还是2字节,或者是3个
然后她根据那4个字节的二进制位,得到有一个占2个字节,有两个占1个字节相似的未知字符,然后输出了他们,也就是???,就想楼上说的

你可以看下基础视频中的21天,06和07,一个是讲转换,一个讲编码的

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马