<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 68, comments - 19, trackbacks - 0, articles - 1

    java編碼問題總結-轉自李騰飛老師

    Posted on 2011-02-15 16:01 viery 閱讀(517) 評論(0)  編輯  收藏 所屬分類: JavaSE

    電腦只能處理011001這樣的二進制數字,字符是日常生活中我們使用的符號,為了電腦能夠存儲、傳輸和展示字符,所以,我們需要把字符轉換為0110000這樣的二進制碼。這就是所謂編碼。相反,把011000這樣的二進制碼轉換為字符的過程就是解碼!JAVA里,char表示一個字符,String表示字符串!

     

    具體把哪個字符映射到哪個二進制串上,是由國家(國家標準)、國際組織(國際標準)等決定的!

     

    一般不用二進制串來表示某個字符的編碼(因為寫起來、閱讀起來都很麻煩),所以一般是用十六進制的串來表示某個字符的編碼。

     

    因此:

    字符 <--> 十六進制串,之間的映射的集合(因為有很多字符),就構成了字符集。

     

    你經常見到的字符集是:Unicode、UTF-8、GB2312、GB18030、GBK、Big-5、ISO-8859-1(又名:Latin-1)

     

    Unicode、UTF-8能夠支持目前世界上所有語言文字的字符

    GB2312是舊的國家標準,不支持繁體漢字

    GBK不是國家標準,但支持繁體漢字

    GB18030是新的國家標準,也支持繁體漢字

    Big-5,能支持繁體漢字

    ISO-8859-1,不支持漢字,英美等拉丁語系的國家常用這個編碼

     

    舉例:

    public class EncodingTest01 {

        public static void main(String[] args) throws Exception{

           String s = "中國";

           byte[] bs = s.getBytes("GB18030");

           System.out.println(Utils.byteArrayToHex(bs));

        }

    }
     
    public class Utils {

        private static char[] hexDigits = {

           '0','1','2','3','4','5','6','7',

           '8','9','A','B','C','D','E','F'

        };

        public static String byteArrayToHex(byte[] bs){

           StringBuffer sb = new StringBuffer();

           for(byte b:bs){

               sb.append(hexDigits[(b >> 4) & 0x0000000F]);

               sb.append(hexDigits[b & 0x0000000F]);

               sb.append(",");

           }

           return sb.toString();

        }

    }
     

     

    “中國”,這兩個簡體漢字,在不同的字符集中,用上述程序輸出,其編碼分別為:

    Unicode – FE,FF,4E,2D,56,FD,

    UTF-8 - E4,B8,AD,E5,9B,BD

    GB18030 - D6,D0,B9,FA,

    ISO-8859-1 - 3F,3F,

     

    解釋:

    關于Unicode

    用Unicode編碼之后的“中國”,其編碼的前面有FE,FF兩個額外的字節。這兩個字節稱為BOM(Byte Order Mark)。“中”這個漢字,它的Unicode編碼是:4E,2D,那么在傳輸的過程中,是把4E放在前面,還是把2D放在前面呢?這有BOM來決定。如果BOM是FEFF(稱為Big Endian),表示4E在前;如果BOM是FFFE(稱為Little Endian),表示2D在前。

     

    也就是說,如果你的文件編碼是Unicode(也可以叫做UTF-16),那么文件開頭的字節就是:FEFF(以這種方式開頭的編碼叫UTF-16BE)或FFFE(以這種方式開頭的編碼叫做UTF-16LE)

     

    UTF-16BE、UTF-16、Unicode是一樣的!

     

    關于UTF-8

    UTF-8編碼的文件,其文件頭也有一段標識:EF BB BF

     

    其它編碼的文件,其文件頭沒有什么標識?。?!

     

    對于使用ISO-8859-1編碼方式來對“中國”二字進行編碼之后,得到的是:3F 3F,這是因為ISO-8859-1字符集中根本就沒有“中國”這兩個字符!所以,它用3F來代替!

     

    解碼
    解碼,實際上就是把二進制流(也就是字節流,即字節數組)轉換為字符。字節數組是什么樣的編碼(即用哪個字符集對它編碼),你必需使用相同的字符集來解碼!

     

    public class EncodingTest02 {

        public static void main(String[] args) throws Exception{

           byte[] bs = {(byte)0xD6,(byte)0xD0,(byte)0xB9,(byte)0xFA};

           String s = new String(bs,"GB18030");

           System.out.println(s);

        }

    }
     

     

    像上述程序所示的那樣,我們知道:D6D0 B9FA 是“中國”兩個字符的“GB18030”編碼,所以,你可以使用這個字符集來把其對應的字節數組解碼為字符!

     

    Java中的字符
    你首先要理解的是,JAVA可以把字符存儲在內存中(即也是以0110010這樣的方式存儲在內存中)!那么,JAVA把字符存儲在內存中的時候,它使用的是什么編碼呢?答案是:Unicode

     

    因此,我們知道,“中國”,這兩個漢字,在內存中,是以“4E,2D,56,FD”這種方式存在的!

     

    不過要注意,JAVA的class文件,是以UTF-8方式編碼的!JAVA虛擬機讀取class文件的時候,通過UTF-8編碼把class文件讀入內存,并轉換為UTF-16(即Unicode)。

     

    因此,new String(byte[],“GB18030“)的真正意思是:把字節流(它是以GB18030方式編碼的)轉換為Unicode的字節流存在內存中!

     


     

    如上圖所示,假設有“中國”兩個漢字,通過getBytes(“encoding”)能將其轉換為不同的編碼!

     

    再看下圖,假設有一個字節流,現在想把它轉換為字符串:

     

     

     

    一個本來是UTF-8編碼的字節流,如果你把它當成ISO-8859-1進行轉換,ISO-8859-1的規則是每個字節一個字符,所以得到了長度為6的字符串,如果你將它輸出,將是亂碼!現在你可以反向轉換,通過ISO-8859-1編碼得到它的字節流,這將原封不動得到一個字節流,然后,你又可以對這個字節流進行正確的解碼了!

     

    簡單總結一下
    如果你拿到一個字節流,你需要清楚的知道,你這個字節流是用哪個字符集進行編碼的!

     

    如果你拿到一個字符串,你發現它輸出的時候是亂碼,那么,你究竟能不能通過某種技術手段解決這個亂碼問題呢?答案是:不一定!

    l           因為你拿到了一個字符串,所以,可以肯定,你拿到的字符串是由于某人將它按照某種字符集將字節流進行了解碼而得到的字符串!

    a)         假如某人是按照ISO-8859-1字符集對字節流進行解碼而得到的字符串,那么,恭喜你,你將可以通過某種技術手段,把你手中的亂碼字符串轉換為正確的字符串!這種技術手段就是:先getBytes(“ISO-8859-1”)得到一個字節流,然后把這個字節流用new String(byte[],“正確的字符集”)轉換為正確的字符串即可!

    b)        假如某人不是按照ISO-8859-1字符集對字節流進行解碼的,那么,很不幸,有很大的可能是你沒有辦法將它再正確地還原了!

     

    頁面編碼
    通過GET方法向后臺遞交的請求
    向服務器遞交的請求中,字符也是需要進行編碼之后傳輸的!瀏覽器將會自動對URL地址中的漢字進行編碼之后傳輸。如果你直接在瀏覽器地址欄輸入URL地址及漢字,那么瀏覽器將自動使用當前操作系統的默認字符集進行編碼(中文操作系統就是GB2312)之后傳輸到服務器;如果你在某個頁面上點擊一個鏈接(此鏈接后面附帶著中文漢字),那么,瀏覽器將自動根據這個頁面所使用的字符集來對漢字進行編碼之后,傳輸到服務器!

     

    比如“中國”兩個漢字,假如頁面編碼是GB18030(或GBK或GB2312),那么向后傳輸的串就是:%D6%D0%B9%FA

     

    比如:http://localhost:8080/myservlet/AddUser?username=%D6%D0%B9%FA

     

    我們后臺使用request.getParameter(“username”)來得到一個字符串,結果發現是亂碼,那么可以肯定,某人幫我們將從客戶端傳輸過來的字節流按照某種字符集解碼成了字符串!某人就是應用服務器(TOMCAT),某種字符集就是應用服務器的默認字符集,是ISO-8859-1。所以,很幸運,還有救!

           String username = request.getParameter("username");

          

           //將它轉換為正確的字符串!

           byte[] bs = username.getBytes("ISO-8859-1");

           username = new String(bs,"GB18030");

          

           //正確

           System.out.println(username);
     

     

    當然,為了避免每次都這樣干,我們干脆修改TOMCAT對于URL編碼的默認解碼字符集即可!

    修改server.xml文件中的下面的語句,加上URIEncoding=“GB18030“的配置即可:

        <Connector port="8080" protocol="HTTP/1.1"

                   connectionTimeout="20000"

                   redirectPort="8443" URIEncoding="GB18030"/>
     

     

    通過POST向后臺遞交的請求
    瀏覽器將按照表單所在的頁面所使用的字符集對數據進行編碼之后傳輸!

     

    在TOMCAT中配置的URIEncoding只對GET方式遞交的請求中的數據有效,而對于POST請求,你必須在調用request.getParameter(“xxx”)之前,調用:request.setCharacterEncoding("GB18030"); !

     

    Response的編碼
     

    在調用response.getWriter()之前,調用response.setCharacterEncoding("GB18030");

    即可!

     

    或者:

    在設置ContentType的時候設置也可以:

    response.setContentType("text/html;charset=GB18030");

     

    本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/li_tengfei/archive/2010/12/25/6098099.aspx

    主站蜘蛛池模板: 亚洲无码黄色网址| 成年女人毛片免费视频| 亚洲国产中文字幕在线观看| 亚洲AV无码片一区二区三区| 免费无码看av的网站| 亚洲精品无码高潮喷水A片软| 97视频热人人精品免费| 亚洲AV无码一区二区三区牛牛| 九九精品免费视频| 亚洲色在线无码国产精品不卡| 特级淫片国产免费高清视频| 亚洲av色香蕉一区二区三区| va亚洲va日韩不卡在线观看| 国产日韩AV免费无码一区二区三区 | 亚洲精品国产精品| 日本成人免费在线| 无码免费又爽又高潮喷水的视频| 亚洲第一视频在线观看免费| 国产高清免费在线| 精品无码专区亚洲| 国产亚洲av片在线观看18女人| 国产成人无码区免费内射一片色欲 | 亚洲毛片一级带毛片基地| 成人免费午夜在线观看| 免费无遮挡无码视频在线观看| 久久国产成人亚洲精品影院 | 国产乱子精品免费视观看片| 亚洲欧洲精品成人久久曰| 亚洲国产成人爱av在线播放| 久久九九免费高清视频| 亚洲av片不卡无码久久| 四虎永久在线精品免费观看地址 | 成全影视免费观看大全二| 人成午夜免费大片在线观看| 亚洲好看的理论片电影| 免费高清av一区二区三区| 一级全免费视频播放| 亚洲大香人伊一本线| 亚洲精品动漫人成3d在线| 日本免费一区二区三区| 精品免费AV一区二区三区|