<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

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

     

    具體把哪個(gè)字符映射到哪個(gè)二進(jìn)制串上,是由國家(國家標(biāo)準(zhǔn))、國際組織(國際標(biāo)準(zhǔn))等決定的!

     

    一般不用二進(jìn)制串來表示某個(gè)字符的編碼(因?yàn)閷懫饋怼㈤喿x起來都很麻煩),所以一般是用十六進(jìn)制的串來表示某個(gè)字符的編碼。

     

    因此:

    字符 <--> 十六進(jìn)制串,之間的映射的集合(因?yàn)橛泻芏嘧址?,就構(gòu)成了字符集。

     

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

     

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

    GB2312是舊的國家標(biāo)準(zhǔn),不支持繁體漢字

    GBK不是國家標(biāo)準(zhǔn),但支持繁體漢字

    GB18030是新的國家標(biāo)準(zhǔn),也支持繁體漢字

    Big-5,能支持繁體漢字

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

     

    舉例:

    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();

        }

    }
     

     

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

    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,

     

    解釋:

    關(guān)于Unicode

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

     

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

     

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

     

    關(guān)于UTF-8

    UTF-8編碼的文件,其文件頭也有一段標(biāo)識(shí):EF BB BF

     

    其它編碼的文件,其文件頭沒有什么標(biāo)識(shí)!!!

     

    對(duì)于使用ISO-8859-1編碼方式來對(duì)“中國”二字進(jìn)行編碼之后,得到的是:3F 3F,這是因?yàn)镮SO-8859-1字符集中根本就沒有“中國”這兩個(gè)字符!所以,它用3F來代替!

     

    解碼
    解碼,實(shí)際上就是把二進(jìn)制流(也就是字節(jié)流,即字節(jié)數(shù)組)轉(zhuǎn)換為字符。字節(jié)數(shù)組是什么樣的編碼(即用哪個(gè)字符集對(duì)它編碼),你必需使用相同的字符集來解碼!

     

    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 是“中國”兩個(gè)字符的“GB18030”編碼,所以,你可以使用這個(gè)字符集來把其對(duì)應(yīng)的字節(jié)數(shù)組解碼為字符!

     

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

     

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

     

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

     

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

     


     

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

     

    再看下圖,假設(shè)有一個(gè)字節(jié)流,現(xiàn)在想把它轉(zhuǎn)換為字符串:

     

     

     

    一個(gè)本來是UTF-8編碼的字節(jié)流,如果你把它當(dāng)成ISO-8859-1進(jìn)行轉(zhuǎn)換,ISO-8859-1的規(guī)則是每個(gè)字節(jié)一個(gè)字符,所以得到了長度為6的字符串,如果你將它輸出,將是亂碼!現(xiàn)在你可以反向轉(zhuǎn)換,通過ISO-8859-1編碼得到它的字節(jié)流,這將原封不動(dòng)得到一個(gè)字節(jié)流,然后,你又可以對(duì)這個(gè)字節(jié)流進(jìn)行正確的解碼了!

     

    簡單總結(jié)一下
    如果你拿到一個(gè)字節(jié)流,你需要清楚的知道,你這個(gè)字節(jié)流是用哪個(gè)字符集進(jìn)行編碼的!

     

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

    l           因?yàn)槟隳玫搅艘粋€(gè)字符串,所以,可以肯定,你拿到的字符串是由于某人將它按照某種字符集將字節(jié)流進(jìn)行了解碼而得到的字符串!

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

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

     

    頁面編碼
    通過GET方法向后臺(tái)遞交的請求
    向服務(wù)器遞交的請求中,字符也是需要進(jìn)行編碼之后傳輸?shù)模g覽器將會(huì)自動(dòng)對(duì)URL地址中的漢字進(jìn)行編碼之后傳輸。如果你直接在瀏覽器地址欄輸入U(xiǎn)RL地址及漢字,那么瀏覽器將自動(dòng)使用當(dāng)前操作系統(tǒng)的默認(rèn)字符集進(jìn)行編碼(中文操作系統(tǒng)就是GB2312)之后傳輸?shù)椒?wù)器;如果你在某個(gè)頁面上點(diǎn)擊一個(gè)鏈接(此鏈接后面附帶著中文漢字),那么,瀏覽器將自動(dòng)根據(jù)這個(gè)頁面所使用的字符集來對(duì)漢字進(jìn)行編碼之后,傳輸?shù)椒?wù)器!

     

    比如“中國”兩個(gè)漢字,假如頁面編碼是GB18030(或GBK或GB2312),那么向后傳輸?shù)拇褪牵?D6%D0%B9%FA

     

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

     

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

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

          

           //將它轉(zhuǎn)換為正確的字符串!

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

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

          

           //正確

           System.out.println(username);
     

     

    當(dāng)然,為了避免每次都這樣干,我們干脆修改TOMCAT對(duì)于URL編碼的默認(rèn)解碼字符集即可!

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

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

                   connectionTimeout="20000"

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

     

    通過POST向后臺(tái)遞交的請求
    瀏覽器將按照表單所在的頁面所使用的字符集對(duì)數(shù)據(jù)進(jìn)行編碼之后傳輸!

     

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

     

    Response的編碼
     

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

    即可!

     

    或者:

    在設(shè)置ContentType的時(shí)候設(shè)置也可以:

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

     

    本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/li_tengfei/archive/2010/12/25/6098099.aspx

    主站蜘蛛池模板: 天堂在线免费观看中文版| 亚洲成av人无码亚洲成av人 | 青青久久精品国产免费看| 亚洲综合一区无码精品| 2017亚洲男人天堂一| 亚洲AV一二三区成人影片| 亚洲午夜国产精品| 亚洲国产成人久久| 亚洲精品第一综合99久久| 亚洲欧美日韩一区二区三区在线| 亚洲欧美国产国产综合一区| 自拍偷自拍亚洲精品播放| 国产在亚洲线视频观看| 一区二区免费国产在线观看| 三级黄色片免费看| 无码人妻丰满熟妇区免费| 99re免费视频| 免费看国产精品3a黄的视频| 男女交性永久免费视频播放 | a视频免费在线观看| 久操视频在线免费观看| 2020因为爱你带字幕免费观看全集 | 亚洲短视频男人的影院| 亚洲日韩中文字幕天堂不卡| 亚洲一级高清在线中文字幕| 亚洲AV无码一区二区三区网址| 精品一区二区三区无码免费直播| 一本到卡二卡三卡免费高| 国产午夜无码精品免费看动漫| 亚洲一区在线免费观看| 免费观看大片毛片| 亚洲综合色在线观看亚洲| 婷婷亚洲综合五月天小说| 亚洲va精品中文字幕| 美女黄频免费网站| 免费91最新地址永久入口| 成人免费视频77777| 亚洲国产成人久久综合碰| 久久久无码精品亚洲日韩蜜臀浪潮| 亚洲欧洲另类春色校园网站| 白白色免费在线视频|