空格變成問號的怪問題

昨天發現,用 HtmlDecode() 去解碼後,“ ”不是被解碼爲半角的空格(ASCII碼0x20)而是變成半角問號“?”(ASCII碼0x3F)。而且奇怪的是,只有每行前面的空格纔會出問題,如果前面後面有漢字的話,空格就還是空格。但是更加奇怪的是,如果直接在HtmlDecode()的後面直接加上trim()的話,這個問號會被去掉。而正常的情況下,問號是不會被去掉的,只有空格纔會被去掉。

       發生這個問題的時候,我是在把解碼後的內容寫入數據庫,因此一直都以爲是sqlserver與應用程序之間的字符集問題或者編碼方式問題。搞了N久,最後才發現在送進SqlServer之前,內容就已經是問號了。

       查了很久,也找不到這個問題如何解決。因此,只能使用山寨解決方法了:

       1、在Decode之前替換   爲 空格。

       2、在Decode之後直接加 Trim()

       顯而易見的,這個不是一個好辦法:在顯示到瀏覽器的時候,空格就不見了

       最近認真去查了一下這個問題,發現問題的關鍵,是編碼方式:如果使用的Encoding是UTF-8的話,就會發生這種情況。

       問題的根源,在於UTF-8這種編碼裏面,存在一個特殊的字符,其編碼是“0xC2 0xA0”,轉換成字符的時候,表現爲一個空格,跟一般的半角空格(ASCII 0x20)一樣,唯一的不同是它的寬度不會被壓縮,因此比較多的被用於網頁排版(如首行縮進之類)。而其他的編碼方式如GB2312、Unicode之類並沒有這樣的字符,因此如果簡單地進行編碼轉換,生成地GB2312/Unocode字符串中,這個字符就會被替換成爲問號(ASCII ox3F)。此時如果進行寫庫、寫文件之類,就會把問號直接寫入了。當然此時會有一種山寨方式:直接替換問號爲空格。可是這種方法,會把原本真正的問號也槍斃掉。

       使用UTF-8進行HTMLDecode的時候,對於語句開頭的( ),就會被自動轉換成爲這個特殊的空格,可能是判斷爲放在開頭的空格,一定是用來排版的。在轉換爲其他編碼之前,這個特殊的空格受到的待遇與普通的半角空格是一致的,甚至也會被trim()去掉。

       因此,碰到這個問題的原因有兩種:一種是在UTF-8編碼下進行了轉換,產生了這個字符;還有一種就是網頁中直接採用了這個字符進行排版。

       知道了具體原因,就有正規的解決方法了。方法就是:在得到UTF-8字符串之後,先進行一個替換,把這個特殊的空格替換爲普通的空格,如果是HTML串,建議替換爲( )。java代碼如下:

        byte[] space = new byte[]{(byte) 0xc2,(byte) 0xa0};
        String UTFSpace  =new String( space,"UTF-8" );
        result=result.replaceAll(UTFSpace, " "); 

   這樣做,就不會把串裏面本來應該有的問號錯誤的替換爲空格。也不會看到討厭的問號,能保存原來字符串的真面目了。
       需要強調的是,替換之前不能進行編碼轉換,一定要繼續使用UTF-8編碼。如果已經轉換成其他編碼,那麼錯誤就已經不可逆轉了。沒有辦法再區分這個錯誤的問號和正常的問號之間的差別了。


原網頁

發佈了16 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章