問題產生
最近遇到一個這樣的問題,在生成的報文中,某個字段信息后面有一個空格,在代碼中trim()下,它仍然存在。到底什么原因呢?
問題的根源
經過多番查證,是由於utf-8中的特俗字符造成的。
問題的根源,在於UTF-8這種編碼里面,存在一個特殊的字符,其編碼是“0xC2 0xA0”,轉換成字符的時候,表現為一個空格,跟一般的半角空格(ASCII 0x20)一樣,唯一的不同是它的寬度不會被壓縮,因此比較多的被用於網頁排版(如首行縮進之類)。而其他的編碼方式如GB2312、Unicode之類並沒有這樣的字符,因此如果簡單地進行編碼轉換,生成地GB2312/Unocode字符串中,這個字符就會被替換成為問號(ASCII ox3F)。
使用UTF-8進行HTMLDecode的時候,對於語句開頭的( ),就會被自動轉換成為這個特殊的空格,可能是判斷為放在開頭的空格,一定是用來排版的。在轉換為其他編碼之前,這個特殊的空格受到的待遇與普通的半角空格是一致的,甚至也會被trim()去掉。
因此,碰到這個問題的原因有兩種:一種是在UTF-8編碼下進行了轉換,產生了這個字符;還有一種就是網頁中直接采用了這個字符進行排版。
問題解決之法
C#代碼如下: byte[] space = new byte[]{0xc2,0xa0};
string UTFSpace = Encoding.GetEncoding("UTF-8").GetString(space);
HtmlStr = HtmlStr.Replace(UTFSpace," "); Java版: byte bytes[] = {(byte) 0xC2,(byte) 0xA0}; String UTFSpace = new String(bytes,"utf-8"); html = html.replaceAll(UTFSpace, " ");
注意: 需要強調的是,替換之前不能進行編碼轉換,一定要繼續使用UTF-8編碼。如果已經轉換成其他編碼,那么錯誤就已經不可逆轉了。沒有辦法再區分這個錯誤的問號和正常的問號之間的差別了。
