本次對(duì)UUZone Refactor中一個(gè)大動(dòng)作就是采用UTF-8編碼,由于種種的歷史原因,uuzone一直采用GBK編碼,現(xiàn)在要把這個(gè)編碼轉(zhuǎn)成為UTF-8的。
本文不打算討論技術(shù), 所以簡(jiǎn)單地說(shuō)明這個(gè)工作進(jìn)展的一個(gè)過(guò)程:
* 最早的時(shí)候,n年前,我們一個(gè)項(xiàng)目需要國(guó)際化支持,毫無(wú)疑問(wèn)utf-8是最佳的編碼選擇,這時(shí)候項(xiàng)目組就遇到了問(wèn)題: 本地編寫(xiě)的文件中的中文都是GBK編碼的, 僅僅設(shè)置頁(yè)面的contentType="text/html; charset=UTF-8", 出來(lái)的全是亂碼...當(dāng)然拿GBK的東西直接要求對(duì)方用UTF-8看,一定是亂碼.?
?? 當(dāng)時(shí)如何解決的過(guò)程已經(jīng)無(wú)法了解, 但最終采用的方案是:? 用GBK寫(xiě)文件, 然后采用JDK中的native2ascii工具轉(zhuǎn)換. 問(wèn)題解決了, 但結(jié)果就是多了轉(zhuǎn)碼的過(guò)程, 轉(zhuǎn)碼后的jsp文件人不可讀.
* 做uuzone了,? 項(xiàng)目組建議采用GBK編碼, 因?yàn)槟莻€(gè)轉(zhuǎn)碼工作太繁瑣了,而且導(dǎo)致文件不可讀, 調(diào)試非常麻煩. 于是uuzone就成了GBK的.
?? 由于采用GBK, 遇到了很多相關(guān)的問(wèn)題... 中途至少有2次我"建議"改用UTF-8, 都被評(píng)估認(rèn)為有太多問(wèn)題而沒(méi)有被采納(郁悶的boss啊...)...
* 發(fā)現(xiàn)原來(lái)不需要轉(zhuǎn)碼!? 終于處于某些原因, 我需要自己動(dòng)手來(lái)研究一些技術(shù)細(xì)節(jié), 發(fā)現(xiàn)native2ascii轉(zhuǎn)碼的工作其實(shí)并不需要進(jìn)行. jsp文件可以直接保存為UTF-8編碼, 輸出的結(jié)果就是UTF-8的...而現(xiàn)在的elips,editplus, ultraedit, 甚至notepad都能保存和識(shí)別utf-8的文件.
* 終于下定決心轉(zhuǎn)為UTF-8. 既然如此, 就沒(méi)有理由拒絕了. 因此本次refactor項(xiàng)目目標(biāo)之一就是改用UTF-8.? 既然文件打算用utf-8保存, 那么就需要批量轉(zhuǎn)換工具...幾下search, 好的工具也找到了.
* 轉(zhuǎn)! ? 有工具, 不到20秒, 6000多個(gè)文件就從GBK轉(zhuǎn)成了UTF-8文件格式...
* 問(wèn)題來(lái)了! 項(xiàng)目中的XML, properties文件是否轉(zhuǎn)碼呢? 本來(lái)計(jì)劃轉(zhuǎn)...但很快發(fā)現(xiàn),這些文件轉(zhuǎn)掉后, XML,properties文件的讀取都出了不同程度的問(wèn)題...總之項(xiàng)目將根本無(wú)法運(yùn)行... 原因何在?原來(lái)這些UTF-8的文件有一個(gè)所謂BOM頭,也就是告訴你這個(gè)文件的編碼是什么...不幸的是Java的xml parser, properties文件parser都不認(rèn)識(shí)這個(gè)BOM頭!已經(jīng)有人把這個(gè)作為Bug提交給了SUN并被接受, 可是這個(gè)bug一直拖了4年,才在去年在Mustang項(xiàng)目(Java 6.0)中解決! 我們顯然不能用了.
* 幸運(yùn)的是... 我們可以規(guī)避這些問(wèn)題, 我們并不需要把XML, properties文件轉(zhuǎn)換成UTF-8的, 只要把jsp轉(zhuǎn)了即可. 雖然一個(gè)項(xiàng)目中的文件兩種保存格式,非常不優(yōu)雅, 但畢竟這能解決問(wèn)題啊... 轉(zhuǎn)換完jsp文件,運(yùn)行項(xiàng)目, 成功! 打開(kāi)browser...頁(yè)面也出來(lái)了!
* 幾乎成功了! 是的, 幾乎成功了...然而在計(jì)算機(jī)的世界里幾乎成功就是不成功. 因?yàn)轫?yè)面上的樣式神秘地出了輕微的混亂. 經(jīng)過(guò)n十分鐘仔細(xì)研究討論, 終于發(fā)現(xiàn)產(chǎn)生的html頁(yè)面內(nèi)出現(xiàn)了幾個(gè)神秘的不可見(jiàn)字符... 就是這些可怕的不可見(jiàn)字符, 破壞了頁(yè)面的結(jié)構(gòu).
* 神秘的隱身字符? 和計(jì)算機(jī)打交道和比人打交道強(qiáng)的一個(gè)地方就是在于 -- 如果計(jì)算機(jī)錯(cuò)了,一定是你錯(cuò)了, 因?yàn)橛?jì)算機(jī)一定忠實(shí)執(zhí)行你的指令. 神秘的不可見(jiàn)字符一定有其來(lái)歷. 經(jīng)過(guò)二進(jìn)制分析, 找到了這些神秘字符出現(xiàn)的地方 ---jsp include! 每次include就會(huì)出現(xiàn)神秘字符, 而這些神秘字符的值也是老朋友了 -- 就是BOM header !?
* 難道不能include了?? 原來(lái)java顯然和xml文件一樣對(duì)待了這些BOM頭, 這些FF FE之類(lèi)的東西成了輸出的一部分. google 去查, 看到一個(gè)人顯然遇到完全相同的問(wèn)題, 可惜是個(gè)俄羅斯的程序員, 也看不懂其文章... :(
??? 怎么辦?? 有同學(xué)說(shuō): 既然你要UTF-8 (心想: 誰(shuí)讓你是boss呢? 愚蠢的boss啊...:-) ) , 我們還是用native2ascii吧...? 不行!?
* 遇到困難要思考. 思考...
??? 首先, 為什么java文件不需要轉(zhuǎn)碼(java 文件中的中文無(wú)論如何都能正確)? 為什么jsp要? jsp不是被預(yù)編譯成java的嗎??
??? 從那個(gè)sun承認(rèn)的bug, 顯然可以得出一個(gè)結(jié)論, java虛擬機(jī)中的file input stream沒(méi)有能自動(dòng)很具BOM識(shí)別文件編碼.?
??? 也許javac是比較native的代碼, 能通過(guò)操作系統(tǒng)獲得native編碼類(lèi)型, 而java內(nèi)部是unicode的, 所以輸出也同樣沒(méi)問(wèn)題.? 而jsp是動(dòng)態(tài)編譯的, 預(yù)編譯器是JVM...其待遇顯然和xml等是一樣的...
?? 難道sun公司的人會(huì)愚蠢到這種地步? 不可能, 一定是我們愚蠢.繼續(xù)google 學(xué)習(xí)...
??? 不幸的是大部分google上關(guān)于這類(lèi)編碼問(wèn)題的討論都是不完整的. 但一個(gè)神秘的pageEncoding跳進(jìn)了眼簾, 已經(jīng)指定了contentType的encoding, 為什么還要指定pageEncoding?? 查一下jsp的資料, 顯然這正是問(wèn)題所在!? pageEncoding就是告訴JVM 這個(gè)jsp本身采用的encoding, 默認(rèn)采用iso-8859. 我們明明用GBK的native編碼, 讓JVM拿iso8859讀取,當(dāng)然不對(duì)了!!
* 根本沒(méi)有需要轉(zhuǎn)碼, 問(wèn)題解決了! 是的, 明白了原因所在, 把所有jsp文件頭修改為: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="GBK" %> 不需要任何轉(zhuǎn)碼,最終輸出的就是UTF-8, 沒(méi)有任何問(wèn)題. 而且這些文件采用native格式保存, 編輯最方便!
posted on 2006-05-28 01:08
老妖 閱讀(2008)
評(píng)論(2) 編輯 收藏