vb.net , c# 簡體繁體之間的轉換
最近在找,簡體與繁體之間轉換時,發現一個寫得不錯的博客: http://www.codeproject.com/KB/webservices/Chinese_Style_Converter.aspx . 如果大家有需要的話,強烈要求到原創那個網頁瀏覽.在這裏只是做一個轉載.
把作者的一些內容貼出來:
享受中文繁簡轉換的樂趣
大家都知道中文有繁體和簡體兩種格式,而且也存在着很多的免費或者負費軟件提供在它們之間轉換的功能,甚至還有提供在Windows 98下同屏幕顯示兩種字體的軟件。而微軟也在這個方面下了不少的努力,Microsoft Word就是其中一個例子。從Visual Basic 6開始就已經提供了這個功能,現在連.net framework也有了這個免費的功能了,而且還是免費的(.net framework distributed本身是免費的,只要使用免費的語言編譯軟件編譯組件就可以享用它了)。
下面就讓我們來看看如何在.net framework中進行中文繁簡轉換,並且也順帶關心一下關於Encoding(編碼)的轉換。最後由於我們正處於面向服務的編程時代,所以我將會把這個功能做成以幾種形式存在的服務以及討論如何做這些服務的部署。
l 繁簡轉換
微軟提供的這個功能在Microsoft.VisualBasic.Strings.StrConv中,十分容易地就可以調用它,下面是一個簡單的將簡體轉爲繁體的例子:
using Microsoft.VisualBasic;
……
string source = “中國是一個美麗的國家。”;
string target = Strings.StrConv(source, VbStrConv.TraditionalChinese, 0);
然後我們就得到了內容爲:“中國是一個美麗的國家。”的字符串target。如果想將繁體轉爲簡體,只需要將第2個參數改爲VBStrConv.SimplifiedChinese就可以了。
當然這個調用簡單的函數還有其他強大的功能,比如提供日文平假名和片假名的轉換等。我建議讀者一定要抽時間讀一下MSDN中關於此功能的介紹。
l Encoding(編碼)轉換
這個世界有很多不同的文字,當被影射爲數字格式的時候,由於各個國家所採用的編碼方式的不同,導致相同的2進制數字可能在不同的編碼方式中代表着不同的內容。GB2312和Big5就是我們所知道的典型的例子。
Unicode的出現就是爲了儘可能地將所有文字都攬括其中(當然,仍然有一部分文字未能包括,比如3級漢字的某些部分就沒有被包括)。但這麼多的編碼方式導致相同的漢字在不同碼制下的2進制數字是幾乎完全不同的,從下面的表格可以看到:
|
中 |
國 |
是 |
一 |
個 |
美 |
麗 |
的 |
國 |
家 |
936 |
D6D0 |
B9FA |
CAC7 |
D2BB |
B8F6 |
C3C0 |
C0F6 |
B5C4 |
B9FA |
BCD2 |
UTF-8 |
E4B8AD |
E59BBD |
E698AF |
E4B880 |
E4B8AA |
E7BE8E |
E4B8BD |
E79A84 |
E59BBD |
E5AEB6 |
UTF-16 |
2D4E |
FD56 |
2F66 |
004E |
2A4E |
8E7F |
3D4E |
8476 |
FD56 |
B65B |
|
中 |
國 |
是 |
一 |
個 |
美 |
麗 |
的 |
國 |
家 |
936 |
D6D0 |
87F8 |
CAC7 |
D2BB |
8280 |
C3C0 |
FB90 |
B5C4 |
87F8 |
BCD2 |
950 |
A4A4 |
B0EA |
AC4F |
A440 |
ADD3 |
ACFC |
C452 |
AABA |
B0EA |
AE61 |
UTF-8 |
E4B8AD |
E59C8B |
E698AF |
E4B880 |
E5808B |
E7BE8E |
E9BA97 |
E79A84 |
E59C8B |
E5AEB6 |
UTF-16 |
2D4E |
0B57 |
2F66 |
004E |
0B50 |
8E7F |
979E |
8476 |
0B57 |
B65B |
在接觸.net framework前,在使用VB6的年代,我是使用ADO.Stream的CopyTo方法來進行編碼轉換的(因爲我只略懂C,更別說C++或者MFC了),當然將GB轉換成UTF-8的時候還需要自己在字節數組中每兩個字節插入一個零字節(對於英文字符),十分弱智。在使用Java後,覺得進行這樣的轉換十分輕鬆。現在使用.net framework也一樣的方便。
.net framework中,進行編碼轉換的是System.Text.Encoding.Convert的方法,調用方法爲:System.Text.Encoding.Convert(Encoding source, Encoding target, byte[] source Bytes)(這個方法存在過載的定義,請閱讀MSDN以獲得更多的信息)。下面是一個簡單的例子:
using System.Text;
……
byte[] source = Encoding.Unicode.GetBytes(“中國是一個美麗的國家”);
byte[] target = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, source);
那麼我們就得到了編碼爲UTF-8格式的字節數組target。
好了,謀殺了一頁多A4紙後,開始到了將上面所說的糅合在一起的時候了。
l 將繁簡和編碼轉換合在一起
我建立了一個叫Converter的類,並且希望可以通過調用其中的一個方法就可以同時實現兩種轉換。另外由於被轉換的中文可能會以多中形式存在(字符串、字節數組、流甚至文件),所以我也希望可以通過方法過載的方式讓不同形式的中文可以轉換到多種形式去。當看到這裏,估計你會知道這會是一個多對多的影射關係。
爲節省篇幅,我不打算複製所有的代碼,所以仍然使用英文版說明中的程序截圖來讓你可以有一個大致的印象:
其中進行轉換的核心代碼的爲:
可以看到,我先進行繁簡體的轉換,然後再進行繁體結果的轉換修正(下面的章節中會提及),最後再將爲Unicode編碼的中間結果轉換成想要的目標編碼。
l 繁體轉換結果的修正
繁體就是有點古怪(否則就不叫繁了),同樣的漢字,不同的搭配場合,樣子就是不一樣。很多軟件都考慮了這方面的問題,比如Microsoft Word。大致做法都是枚舉所有與字級別的轉換後結果不符合搭配的場合的話,再將這些內容進行替換。大家可以看看下面的這個搭配的例子:
Simplified Chinese |
Traditional Chinese |
頭髮 |
頭髮 |
發達 |
發達 |
注意 |
注意 |
備註 |
備註 |
繁體的繁可見一斑。我打算使用類似的解決辦法,將要替換的內容放到XML文件中,然後讀入內存,以提供轉換使用。爲避免單字轉換覆蓋詞轉換,詞轉換覆蓋句子轉換的情形,我使用了System.Data.DataTable來存放這些內容,並按照它們的長度進行從小到大的排序。另外,爲處理詞組中包含空格的問題,比如:“頭髮”和“頭 發”其實有可能是由於要調整空位而估計加空格,所以在檢測和進行內容替換的時候,還需要考慮中間可能有空格的情況:
另外由於我們可能會不斷地完善自己的繁簡轉換調整XML文件,而當這個功能變成服務的時候,總不可能停下這個服務來讓它得到內容的更新吧?所以我就建立了一個提供設置信息的類,這個類使用FileWatcher來監視在公共屬性中制定的的XML文件,一旦文件被修改,它將會在再次調用轉換功能的時候將這個XML文件的內容重新裝載。
還有,值得一提的是,我們還可以用這個功能來進行一些詞語方面不同的轉換,例如:字節 vs. 位元, 圖標 vs. 圖示,窗口 vs. 視窗等。
l 做一個調用Converter類的工具
做完Converter類後,我想通過做一個調用它的簡單工具來作爲示範的例子。當然這個簡單的工具自然是有一定使用價值的啦。
我建立了一個WinForm的程序來調用Converter類,另外由於需要對下面提及的服務進行示例,我使用了可以在config文件中定義調用本地組件、Web Service和.net remoting 3種調用形式的做法。在建立WinForm程序之前,我先建立一個WinForm Control來實現所有的功能,然後纔將此控件放到一個WinForm中,之所以這樣做,是因爲我還希望可以在IE中,通過實現ActiveX控件(確切地說是類似Java Applet)的方式來在網頁中可以使用這個轉換的功能。
核心的類已經做好,下面讓我們來看看如何把它變成一個服務,讓其他計算機來調用。做成服務的魅力就是其他計算機可以不需要安裝這個組件,僅需要通過固定的接口來調用就可以享受到這個功能。並且服務由於是基於接口來提供的,所以享受服務的可以是用各種不同語言來編寫的客戶端。而且在更新的時候只需要考慮做單點維護就可以了。好啦,歡迎來到面向服務的年代。
l COM+ Application
Java和.net橫行的年代,大家都衝着更新、更美好的事物去了,但誰來關心那些已經寫好並且在過去的幾年,甚至今後一年內仍然是穩固地提供服務的基於COM/DCOM的應用程序呢?答案是:還是我們這些做軟件的。在未來得及把所有軟件重寫一遍的時候,想不想舊的應用程序,或者新的但卻仍然使用COM/DCOM的程序也能享受到中文繁簡和編碼轉換的好處呢?
我當然想,所以第一個要做的服務就是將Converter類封裝到COM+ Application中。遵從MSDN的指引,寫一個包裝Converter的繼承System.EnterpriseServices.ServicedComponent的類,是十分容易的。當然要小心,爲了同時提供早綁定和晚綁定,並且還需要防止每次做註冊時都會自動生成新的GUID,還有爲避免在以後修改接口的時候會在COM+ Application中留下對COM來說會衝突的問題,我們需要定義固定的GUID,並且先寫好Interface的定義,最後還需要在自己的新類裏實現所定義的Interface和使用[ClassInterface(ClassInterfaceType.None)]的屬性。
部署這個寫好的類可以有3種常用的方法:
1. 讓程序第一次調用的時候讓.net framework幫忙建立COM+ Application
2. 使用Regsvcs.exe建立COM+ Application
3. 使用Installer類來自定義註冊的行爲,然後通過Regsvcs.exe或者Windows Installer來建立COM+ Application
我是一個很懶惰的人,當然希望什麼事都自動做好是最方便的。第一種方法雖然舒服和瀟灑,但卻需要第一個調用的人擁有服務器本地管理員權限纔可以;但現實生活中,一般用戶總不會擁有服務器的管理員權限,那麼這個差事還是一樣要落到自己或者管理員的手上。既然至少都要乾點什麼,那麼就還是不要太懶惰吧。第二種方法方便,但要自己輸入命令或者至少先建立個快捷方式啊。第三種看起來比較專業,安裝和卸載起來也方便(交給Windows Installer就可以啦),而且還可以定義其他的行爲。
那麼就用第三種方式吧。
按照MSDN的指引,編寫一個Installer類,分別重載Install和Uninstall事件就可以了(其他的交給Windows Installer就是啦):
然後我們甚至可以通過Windows Host Script來調用它(當然實現要在客戶端做類的註冊,請閱讀MSDN中相關的內容):
dim objConverter
set objConverter = createobject("ChineseUtilComPlus.ConverterService", “MyServer”)
msgbox objConverter.StringToStringEncodingIntegerFormat("中國是一個美麗的國家", 2, 936, 65001, 936)
set objConverter = nothing
l .net remoting
DCOM的升級版本就是.net remoting,雖然Web Service流行,但.net remoting仍然是在速度和便利方面上來說的利器。通常我們會在IIS或者Windows Service中提供.net remoting的服務。我打算在Windows Service中提供Converter類的服務。
編寫一個繼承System.ServiceProcess.ServiceBase的封裝Converter類的類後,還需要在config文件中加入支持指定中文繁簡轉換替換的XML文件的定義,另外還加入了定義這個服務是通過http和tcp來提供調用的定義:
然後,當然還是再做一個幫助部署的Installer類啦(其他的讓Windows Installer去管好了):
l Web Service
Web Service的好處就是可以讓使用SOAP的應用程序可以調用,其中的魅力和前景就不再多說了。
但在建立Web Service之前,我們需要做一些取捨:System.Text.Encoding和Stream都不能直接做XML序列化,而且因爲懶,我也不打算做。所以就提供使用int和string類型來定義System.Text.Encoding的方法,然後通過System.Text.Encoding.GetEncoding的功能來取得System.Text.Encoding。另外也放棄了對Stream轉換的支持。最後,由於安全因素的考慮,還放棄了對文件轉換的支持。
最後,我只針對字節數組和字符串的轉換做了封裝。當然,也少不了在web.config裏提供定義中文繁簡轉換替換的XML文件支持。
l 部署
只要遵照MSDN的指引,建立服務不難。但如果要用Visual Studio.net 2003來建立Windows Installer安裝包,我發現在MSDN裏可以獲得的資源卻是少得可憐。
我需要花更多的時間來弄明白如何可以用Visual Studio.net 2003來建立可以讓用戶選擇性部署所有或者部分服務的Windows Installer安裝包。最後,我決定將針對每個服務都先做一個Merge Module,然後再使用一個Setup Package來包括所有的Merge Module,最後再定義一些選擇的界面。還有通過和選擇相對應的自定義屬性來控制哪個服務將會被安裝。
當然使用其他的安裝包軟件也是很容易的,象Wise Installer for Windows Installer等。
l 其他可以做的?
當然還有其他值得完善的方面,我們其實還可以
1. 讓用戶選擇.net remoting是同時支持http和tcp,還是其中之一?
2. 還有可以讓用戶輸入使用什麼端口來提供服務
3. 對Converter類提供異步的轉換功能
4. 對Converter加入對整個目錄的符合條件的文件做批量轉換的功能
5. 還有更多的,只要想得到就是了
我沒有把太多的代碼放上來(因爲實在是太簡單了),但仍然希望如果你有空的話,可以粗略瀏覽一番。中文繁簡轉換是一個很簡單的功能,但其實我們可以按照這樣的思想,把更多有用的功能變成服務,然後讓更多的程序來盡情享用。
盡情享受中文繁簡轉換吧! :-P