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

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

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

    隨筆 - 6  文章 - 129  trackbacks - 0
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(14)

    隨筆檔案(6)

    文章分類(lèi)(467)

    文章檔案(423)

    相冊(cè)

    收藏夾(18)

    JAVA

    搜索

    •  

    積分與排名

    • 積分 - 825755
    • 排名 - 49

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    幾種誤解,以及亂碼產(chǎn)生的原因和解決辦法
    3.1 容易產(chǎn)生的誤解
      對(duì)編碼的誤解
    誤解一 在將“字節(jié)串”轉(zhuǎn)化成“UNICODE 字符串”時(shí),比如在讀取文本文件時(shí),或者通過(guò)網(wǎng)絡(luò)傳輸文本時(shí),容易將“字節(jié)串”簡(jiǎn)單地作為單字節(jié)字符串,采用每“一個(gè)字節(jié)”就是“一個(gè)字符”的方法進(jìn)行轉(zhuǎn)化。

    而實(shí)際上,在非英文的環(huán)境中,應(yīng)該將“字節(jié)串”作為 ANSI 字符串,采用適當(dāng)?shù)木幋a來(lái)得到 UNICODE 字符串,有可能“多個(gè)字節(jié)”才能得到“一個(gè)字符”。

    通常,一直在英文環(huán)境下做開(kāi)發(fā)的程序員們,容易有這種誤解。
    誤解二 在 DOS,Windows 98 等非 UNICODE 環(huán)境下,字符串都是以 ANSI 編碼的字節(jié)形式存在的。這種以字節(jié)形式存在的字符串,必須知道是哪種編碼才能被正確地使用。這使我們形成了一個(gè)慣性思維:“字符串的編碼”。

    當(dāng) UNICODE 被支持后,Java 中的 String 是以字符的“序號(hào)”來(lái)存儲(chǔ)的,不是以“某種編碼的字節(jié)”來(lái)存儲(chǔ)的,因此已經(jīng)不存在“字符串的編碼”這個(gè)概念了。只有在“字符串”與“字節(jié)串”轉(zhuǎn)化時(shí),或者,將一個(gè)“字節(jié)串”當(dāng)成一個(gè) ANSI 字符串時(shí),才有編碼的概念。

    不少的人都有這個(gè)誤解。

    第一種誤解,往往是導(dǎo)致亂碼產(chǎn)生的原因。第二種誤解,往往導(dǎo)致本來(lái)容易糾正的亂碼問(wèn)題變得更復(fù)雜。

    在這里,我們可以看到,其中所講的“誤解一”,即采用每“一個(gè)字節(jié)”就是“一個(gè)字符”的轉(zhuǎn)化方法,實(shí)際上也就等同于采用 iso-8859-1 進(jìn)行轉(zhuǎn)化。因此,我們常常使用 bytes = string.getBytes("iso-8859-1") 來(lái)進(jìn)行逆向操作,得到原始的“字節(jié)串”。然后再使用正確的 ANSI 編碼,比如 string = new String(bytes, "GB2312"),來(lái)得到正確的“UNICODE 字符串”。

    3.2 非 UNICODE 程序在不同語(yǔ)言環(huán)境間移植時(shí)的亂碼

    非 UNICODE 程序中的字符串,都是以某種 ANSI 編碼形式存在的。如果程序運(yùn)行時(shí)的語(yǔ)言環(huán)境與開(kāi)發(fā)時(shí)的語(yǔ)言環(huán)境不同,將會(huì)導(dǎo)致 ANSI 字符串的顯示失敗。

    比如,在日文環(huán)境下開(kāi)發(fā)的非 UNICODE 的日文程序界面,拿到中文環(huán)境下運(yùn)行時(shí),界面上將顯示亂碼。如果這個(gè)日文程序界面改為采用 UNICODE 來(lái)記錄字符串,那么當(dāng)在中文環(huán)境下運(yùn)行時(shí),界面上將可以顯示正常的日文。

    由于客觀原因,有時(shí)候我們必須在中文操作系統(tǒng)下運(yùn)行非 UNICODE 的日文軟件,這時(shí)我們可以采用一些工具,比如,南極星,AppLocale 等,暫時(shí)的模擬不同的語(yǔ)言環(huán)境。

    3.3 網(wǎng)頁(yè)提交字符串

    當(dāng)頁(yè)面中的表單提交字符串時(shí),首先把字符串按照當(dāng)前頁(yè)面的編碼,轉(zhuǎn)化成字節(jié)串。然后再將每個(gè)字節(jié)轉(zhuǎn)化成 "%XX" 的格式提交到 Web 服務(wù)器。比如,一個(gè)編碼為 GB2312 的頁(yè)面,提交 "中" 這個(gè)字符串時(shí),提交給服務(wù)器的內(nèi)容為 "%D6%D0"。

    在服務(wù)器端,Web 服務(wù)器把收到的 "%D6%D0" 轉(zhuǎn)化成 [0xD6, 0xD0] 兩個(gè)字節(jié),然后再根據(jù) GB2312 編碼規(guī)則得到 "中" 字。

    在 Tomcat 服務(wù)器中,request.getParameter() 得到亂碼時(shí),常常是因?yàn)榍懊嫣岬降?#8220;誤解一”造成的。默認(rèn)情況下,當(dāng)提交 "%D6%D0" 給 Tomcat 服務(wù)器時(shí),request.getParameter() 將返回 [0x00D6, 0x00D0] 兩個(gè) UNICODE 字符,而不是返回一個(gè) "中" 字符。因此,我們需要使用 bytes = string.getBytes("iso-8859-1") 得到原始的字節(jié)串,再用 string = new String(bytes, "GB2312") 重新得到正確的字符串 "中"。

    3.4 從數(shù)據(jù)庫(kù)讀取字符串

    通過(guò)數(shù)據(jù)庫(kù)客戶(hù)端(比如 ODBC 或 JDBC)從數(shù)據(jù)庫(kù)服務(wù)器中讀取字符串時(shí),客戶(hù)端需要從服務(wù)器獲知所使用的 ANSI 編碼。當(dāng)數(shù)據(jù)庫(kù)服務(wù)器發(fā)送字節(jié)流給客戶(hù)端時(shí),客戶(hù)端負(fù)責(zé)將字節(jié)流按照正確的編碼轉(zhuǎn)化成 UNICODE 字符串。

    如果從數(shù)據(jù)庫(kù)讀取字符串時(shí)得到亂碼,而數(shù)據(jù)庫(kù)中存放的數(shù)據(jù)又是正確的,那么往往還是因?yàn)榍懊嫣岬降?#8220;誤解一”造成的。解決的辦法還是通過(guò) string = new String( string.getBytes("iso-8859-1"), "GB2312") 的方法,重新得到原始的字節(jié)串,再重新使用正確的編碼轉(zhuǎn)化成字符串。

    3.5 電子郵件中的字符串

    當(dāng)一段 Text 或者 HTML 通過(guò)電子郵件傳送時(shí),發(fā)送的內(nèi)容首先通過(guò)一種指定的字符編碼轉(zhuǎn)化成“字節(jié)串”,然后再把“字節(jié)串”通過(guò)一種指定的傳輸編碼(Content-Transfer-Encoding)進(jìn)行轉(zhuǎn)化得到另一串“字節(jié)串”。比如,打開(kāi)一封電子郵件源代碼,可以看到類(lèi)似的內(nèi)容:

    Content-Type: text/plain;
            charset="gb2312"
    Content-Transfer-Encoding: base64

    sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==

    最常用的 Content-Transfer-Encoding 有 Base64 和 Quoted-Printable 兩種。在對(duì)二進(jìn)制文件或者中文文本進(jìn)行轉(zhuǎn)化時(shí),Base64 得到的“字節(jié)串”比 Quoted-Printable 更短。在對(duì)英文文本進(jìn)行轉(zhuǎn)化時(shí),Quoted-Printable 得到的“字節(jié)串”比 Base64 更短。

    郵件的標(biāo)題,用了一種更簡(jiǎn)短的格式來(lái)標(biāo)注“字符編碼”和“傳輸編碼”。比如,標(biāo)題內(nèi)容為 "中",則在郵件源代碼中表示為:

    // 正確的標(biāo)題格式
    Subject: =?GB2312?B?1tA=?=

    其中,

    • 第一個(gè)“=?”與“?”中間的部分指定了字符編碼,在這個(gè)例子中指定的是 GB2312。
    • “?”與“?”中間的“B”代表 Base64。如果是“Q”則代表 Quoted-Printable。
    • 最后“?”與“?=”之間的部分,就是經(jīng)過(guò) GB2312 轉(zhuǎn)化成字節(jié)串,再經(jīng)過(guò) Base64 轉(zhuǎn)化后的標(biāo)題內(nèi)容。

    如果“傳輸編碼”改為 Quoted-Printable,同樣,如果標(biāo)題內(nèi)容為 "中":

    // 正確的標(biāo)題格式
    Subject: =?GB2312?Q?=D6=D0?=

    如果閱讀郵件時(shí)出現(xiàn)亂碼,一般是因?yàn)?#8220;字符編碼”或“傳輸編碼”指定有誤,或者是沒(méi)有指定。比如,有的發(fā)郵件組件在發(fā)送郵件時(shí),標(biāo)題 "中":

    // 錯(cuò)誤的標(biāo)題格式
    Subject: =?ISO-8859-1?Q?=D6=D0?=

    這樣的表示,實(shí)際上是明確指明了標(biāo)題為 [0x00D6, 0x00D0],即 "中",而不是 "中"。

    4. 幾種錯(cuò)誤理解的糾正

    誤解:“ISO-8859-1 是國(guó)際編碼?”

    非也。iso-8859-1 只是單字節(jié)字符集中最簡(jiǎn)單的一種,也就是“字節(jié)編號(hào)”與“UNICODE 字符編號(hào)”一致的那種編碼規(guī)則。當(dāng)我們要把一個(gè)“字節(jié)串”轉(zhuǎn)化成“字符串”,而又不知道它是哪一種 ANSI 編碼時(shí),先暫時(shí)地把“每一個(gè)字節(jié)”作為“一個(gè)字符”進(jìn)行轉(zhuǎn)化,不會(huì)造成信息丟失。然后再使用 bytes = string.getBytes("iso-8859-1") 的方法可恢復(fù)到原始的字節(jié)串。

    誤解:“Java 中,怎樣知道某個(gè)字符串的內(nèi)碼?”

    Java 中,字符串類(lèi) java.lang.String 處理的是 UNICODE 字符串,不是 ANSI 字符串。我們只需要把字符串作為“抽象的符號(hào)的串”來(lái)看待。因此不存在字符串的內(nèi)碼的問(wèn)題。



    posted on 2007-09-13 22:34 Ke 閱讀(1520) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): encoding
    主站蜘蛛池模板: 久久国产高潮流白浆免费观看| 九九九国产精品成人免费视频| 中文字幕版免费电影网站| 国产伦一区二区三区免费| 亚洲精品无码成人| 嫩草影院免费观看| 亚洲AV无码国产一区二区三区 | 国产视频精品免费视频| 免费午夜爽爽爽WWW视频十八禁 | 中文精品人人永久免费| 国产自偷亚洲精品页65页| 97国免费在线视频| 久久亚洲免费视频| 日本妇人成熟免费中文字幕| 亚洲视频在线观看2018| 蜜桃精品免费久久久久影院| AV激情亚洲男人的天堂国语| 免费大黄网站在线观| 大妹子影视剧在线观看全集免费 | 精品亚洲成a人片在线观看少妇| 99久久免费观看| 亚洲入口无毒网址你懂的| 好爽好紧好大的免费视频国产| 男女猛烈激情xx00免费视频| 亚洲精品字幕在线观看| 久久免费看黄a级毛片 | va亚洲va日韩不卡在线观看| 一级做受视频免费是看美女| 国产精品亚洲精品日韩已满| 麻豆视频免费观看| 国产AV无码专区亚洲AV琪琪| 亚洲自偷自偷在线制服 | jizzjizz亚洲日本少妇| 国产亚洲精品久久久久秋霞| 91福利免费体验区观看区| 亚洲AV成人一区二区三区观看| 亚洲精品自在在线观看| 91情侣在线精品国产免费| 美女啪啪网站又黄又免费| 久久亚洲精品中文字幕无码| 思思99re66在线精品免费观看|