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

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

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

    Rookie

    Headache English

    數據加載中……
    J2EE開發中字符處理
            在java企業級開發中,會有多處涉及到字符集編碼,有些地方需要進行正確的設置,有些地方需要進行一定程度的處理。

    一,java中對字符的處理

            getBytes(charset):這是java字符串處理的一個標準函數,其作用是將字符串所表示的字符按照charset編碼,并以字節方式表示。注意字符串在java內存中總是按unicode編碼存儲的。比如"中文",正常情況下(即沒有錯誤的時候)存儲為"4e2d 6587",如果charset為"gbk",則被編碼為"d6d0 cec4",然后返回字節"d6 d0 ce c4"。如果charset為"utf8"則最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1",則由于無法編碼,最后返回 "3f 3f"(兩個問號)。
            new String(charset)這是java字符串處理的另一個標準函數,和上一個函數的作用相反,將字節數組按照charset編碼進行組合識別,最后轉換為unicode存儲。參考上述getBytes的例子,"gbk" 和"utf8"都可以得出正確的結果"4e2d 6587",但iso8859-1最后變成了"003f 003f"(兩個問號)。因為utf8可以用來表示/編碼所有字符,所以new String( str.getBytes( "utf8" ), "utf8" ) == str,即完全可逆。
           
    setCharacterEncoding()該函數用來設置http請求或者相應的編碼。對于request,是指提交內容的編碼,指定后可以通過getParameter()則直接獲得正確的字符串,如果不指定,則默認使用iso8859-1編碼,需要進一步處理。參見下述"表單輸入"。值得注意的是在執行setCharacterEncoding()之前,不能執行任何getParameter()。java doc上說明:This method must be called prior to reading request parameters or reading input using getReader()。而且,該指定只對POST方法有效,對GET方法無效。分析原因,應該是在執行第一個getParameter()的時候,java將會按照編碼分析所有的提交內容,而后續的getParameter()不再進行分析,所以setCharacterEncoding()無效。而對于GET方法提交表單是,提交的內容在URL中,一開始就已經按照編碼分析所有的提交內容,setCharacterEncoding()自然就無效。對于response,則是指定輸出內容的編碼,同時,該設置會傳遞給瀏覽器,告訴瀏覽器輸出內容所采用的編碼。

    二,web開發中字符編碼幾處設置
           對于web應用程序,和編碼有關的設置或者函數如下。
            jsp編譯:指定文件的存儲編碼,很明顯,該設置應該置于文件的開頭。例如:<@pagepageEncoding="GBK"%>。另外,對于一般class文件,可以在編譯的時候指定編碼。
            
    jsp輸出:指定文件輸出到browser是使用的編碼,該設置也應該置于文件的開頭。例如:<%@ page contentType="text/html; charset= GBK" %>。該設置和response.setCharacterEncoding("GBK")等效。
            
    meta設置:指定網頁使用的編碼,該設置對靜態網頁尤其有作用。因為靜態網頁無法采用jsp的設置,而且也無法執行response.setCharacterEncoding()。例如:<META http-equiv="Content-Type" content="text/html; charset=GBK" />,如果同時采用了jsp輸出和meta設置兩種編碼指定方式,則jsp指定的優先。因為jsp指定的直接體現在response中。需要注意的是,apache有一個設置可以給無編碼指定的網頁指定編碼,該指定等同于jsp的編碼指定方式,所以會覆蓋靜態網頁中的meta指定。所以有人建議關閉該設置。
            
    form設置:當瀏覽器提交表單的時候,可以指定相應的編碼。例如:<form accept-charset= "gb2312">。一般不必不使用該設置,瀏覽器會直接使用網頁的編碼。

    三,URL地址

            URL地址中含有中文字符是很麻煩的,前面描述過使用GET方法提交表單的情況,使用GET方法時,參數就是包含在URL中。
            URL編碼:對于URL中的一些特殊字符,瀏覽器會自動進行編碼。這些字符除了"/?&"等外,還包括unicode字符,比如漢子。這時的編碼比較特殊。
            
    IE有一個選項"總是使用UTF-8發送URL",當該選項有效時,IE將會對特殊字符進行UTF-8編碼,同時進行URL編碼。如果改選項無效,則使用默認編碼"GBK",并且不進行URL編碼。但是,對于URL后面的參數,則總是不進行編碼,相當于UTF-8選項無效。比如"中文.html?a=中文",當UTF-8選項有效時,將發送鏈接"%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87";而UTF-8選項無效時,將發送鏈接"\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"兩個字只有4個字節,而前者卻有18個字節,這主要時URL編碼的原因。當web server(tomcat)接收到該鏈接時,將會進行URL解碼,即去掉"%",同時按照ISO8859-1編碼(上面已經描述,可以使用URLEncoding來設置成其它編碼)識別。上述例子的結果分別是"\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"和"\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87",注意前者前面的"中文"兩個字恢復成了6個字符。這里用"\u",表示是unicode。所以,由于客戶端設置的不同,相同的鏈接,在服務器上得到了不同結果。這個問題不少人都遇到,卻沒有很好的解決辦法。所以有的網站會建議用戶嘗試關閉UTF-8選項。不過,下面會描述一個更好的處理辦法。
            
    rewrite:熟悉的人都知道,apache有一個功能強大的rewrite模塊,這里不描述其功能。需要說明的是該模塊會自動將URL解碼(去除%),即完成上述web server(tomcat)的部分功能。有相關文檔介紹說可以使用[NE]參數來關閉該功能,但我試驗并未成功,可能是因為版本(我使用的是apache 2.0.54)問題。另外,當參數中含有"?& "等符號的時候,該功能將導致系統得不到正常結果。rewrite本身似乎完全是采用字節處理的方式,而不考慮字符串的編碼,所以不會帶來編碼問題。
            
    URLEncode.encode():這是Java本身提供對的URL編碼函數,完成的工作和上述UTF-8選項有效時瀏覽器所做的工作相似。值得說明的是,java已經不贊成不指定編碼來使用該方法(deprecated)。應該在使用的時候增加編碼指定。當不指定編碼的時候,該方法使用系統默認編碼,這會導致軟件運行結果得不確定。比如對于"中文",當系統默認編碼為"gb2312"時,結果是"%4e%2d%65%87",而默認編碼為"UTF-8",結果卻是"%e4%b8%ad%e6%96%87",后續程序將難以處理。另外,這兒說的系統默認編碼是由運行tomcat時的環境變量LC_ALL和LANG等決定的,曾經出現過tomcat重啟后就出現亂碼的問題,最后才郁悶的發現是因為修改修改了這兩個環境變量。建議統一指定為"UTF-8"編碼,可能需要修改相應的程序。
            
            
    一個解決方案
           上面說起過,因為瀏覽器設置的不同,對于同一個鏈接,web server收到的是不同內容,而軟件系統有無法知道這中間的區別,所以這一協議目前還存在缺陷。
            
    針對具體問題,不應該僥幸認為所有客戶的IE設置都是UTF-8有效的,也不應該粗暴的建議用戶修改IE設置,要知道,用戶不可能去記住每一個web server的設置。所以,接下來的解決辦法就只能是讓自己的程序多一點智能:根據內容來分析編碼是否UTF-8。   
            
    比較幸運的是UTF-8編碼相當有規律,所以可以通過分析傳輸過來的鏈接內容,來判斷是否是正確的UTF-8字符,如果是,則以UTF-8處理之,如果不是,則使用客戶默認編碼(比如"GBK"),下面是一個判斷是否UTF-8的例子,如果你了解相應規律,就容易理解

    public static boolean isValidUtf8(byte[] b,int aMaxCount){

           
    int lLen=b.length,lCharCount=0;

           
    for(int i=0;i<lLen && lCharCount<aMaxCount;++lCharCount){

                  
    byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;)

                  
    if(lByte>=0continue;//>=0 is normal ascii

                  
    if(lByte<(byte)0xc0 || lByte>(byte)0xfreturn false;

                  
    int lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4

                         :lByte
    >(byte)0xf0?3:lByte>(byte)0xe0?2:1;

                  
    if(i+lCount>lLen) return false;

                  
    for(int j=0;j<lCount;++j,++i) if(b[i]>=(byte)0xc0return false;

           }

           
    return true;

    }

    相應地,一個使用上述方法的例子如下:

    public static String getUrlParam(String aStr,String aDefaultCharset)

    throws UnsupportedEncodingException{

           
    if(aStr==nullreturn null;

           
    byte[] lBytes=aStr.getBytes("ISO-8859-1");

           
    return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset);

    }

    不過,該方法也存在缺陷,如下兩方面:
            
    沒有包括對用戶默認編碼的識別,這可以根據請求信息的語言來判斷,但不一定正確,因為我們有時候也會輸入一些韓文,或者其他文字。
            
    可能會錯誤判斷UTF-8字符,一個例子是"學習"兩個字,其GBK編碼是" \xd1\xa7\xcf\xb0",如果使用上述isValidUtf8方法判斷,將返回true。可以考慮使用更嚴格的判斷方法,不過估計效果不大。
            
    有一個例子可以證明google也遇到了上述問題,而且也采用了和上述相似的處理方法,比如,如果在地址欄中輸入"http://www.google.com/search?hl=zh-CN&newwindow=1&q=學習",google將無法正確識別,而其他漢字一般能夠正常識別。最后,應該補充說明一下,如果不使用rewrite規則,或者通過表單提交數據,其實并不一定會遇到上述問題,因為這時可以在提交數據時指定希望的編碼。另外,中文文件名確實會帶來問題,應該謹慎使用。

    四,過濾器
            
    如果需要統一設置編碼,則通過filter進行設置是個不錯的選擇。在filter class中,可以統一為需要的請求或者回應設置編碼。參加上述setCharacterEncoding()。這個類apache已經給出了可以直接使用的例SetCharacterEncodingFilter。

    posted on 2008-01-05 17:36 zhhang920 閱讀(301) 評論(0)  編輯  收藏 所屬分類: J2EE

    主站蜘蛛池模板: 亚洲精品国偷自产在线| 老牛精品亚洲成av人片| 9277手机在线视频观看免费| 亚洲午夜福利在线观看| 在线播放免费人成视频网站| 亚洲区日韩区无码区| 免费无遮挡无码视频在线观看| 亚洲 国产 图片| 国产亚洲综合久久系列| 国产免费黄色无码视频| 亚洲国产a级视频| 色哟哟国产精品免费观看| 亚洲精品国产精品乱码不卡| 一级特黄a免费大片| 最近2019免费中文字幕视频三| 久久精品国产亚洲av麻豆小说| 老汉精品免费AV在线播放| 亚洲黄色中文字幕| 天天影视色香欲综合免费| 亚洲AV色吊丝无码| 免费电视剧在线观看| 久久久久亚洲国产| 国产成人免费手机在线观看视频| 久久久久久久久无码精品亚洲日韩| 国产乱子伦精品免费女| 永久免费精品影视网站| 亚洲精品无码不卡在线播HE | 足恋玩丝袜脚视频免费网站| 亚洲日本一区二区三区| 亚洲免费视频播放| 亚洲日韩中文字幕一区| 又粗又硬又黄又爽的免费视频| 一级人做人a爰免费视频| 亚洲精品色午夜无码专区日韩| 一区二区三区观看免费中文视频在线播放 | 十八禁在线观看视频播放免费| 亚洲精品乱码久久久久久久久久久久| 久久久久久影院久久久久免费精品国产小说| 亚洲一区二区三区首页| 成人免费毛片内射美女-百度| 亚洲av无码有乱码在线观看|