最近寫的一個C++程式裡需要處理不同語言編碼之間的相互轉換問題,主要是GBK、BIG5、UTF-8和UTF-16這幾種編碼,程式雖小,但轉換操作相對複雜一些。起初只想用C++本身提供的功能——包括C++標準裡的wchar_t類型,C語言運行庫中的locale函數集、mbstowcs和wcstombs函數,以及標準C++庫中的wstring、wfstream等類——解決問題。不過,實際編起程式來,這些東西雖然能實現編碼轉換的功能,但總顯得比較繁瑣,缺少物件導向的流暢感。最討厭的是,不同的C++編譯器對這些東西的支援程度也不一樣,vc相對好一些,其他的總要調上半天才能運行起來,有時還會碰上奇怪的編碼錯誤。
現在想一想,以前在MFC中,直接用CString或TCHAR數組儲存字串,用WIN32的MultiByteToWideChar和WideCharToMultiByte函數處理編碼轉換的做法也比上面的方法好不到哪兒去,而且更難於移植。
所以,這會兒就特別懷念用Java語言處理類似問題的愜意了,Java本身的char類型就是UNICODE的,同時又在API中提供了物件導向的編碼轉換機制。所以,在Java中,下面這種轉換檔編碼的操作看上去就相當舒服:
InputStreamReader in = new InputStreamReader(new FileInputStream(old_name), "BIG5");
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(new_name), "GBK");
while((i = in.read()) >= 0)
out.write(i);
更複雜的編碼轉換問題,在Java中解決起來也非常簡單。這裡面最本質的問題在哪裡呢?是不是Java把自己的核心(“核心”這個詞不恰當,有點兒像以前說的“核心級漢化”了)設計成UNICODE的緣故呢?換句話說,是不是Java裡char類型本身就是UNICODE類型帶來的好處呢?.NET平台的語言,像C#和VB.NET也是按照類似Java的模式設計的,在這些語言中處理編碼轉換問題似乎也很方便。C/C++是後來才引入的國際化功能,char和wchar_t也是相互分離的,是不是必然會有許多麻煩呢?
前幾天在Linux上寫一個Ruby指令碼,用於管理和監控我自己家裡的寬頻連線(我對Ruby不熟,是邊查Ruby手冊邊寫程式的),發現Ruby內建的字元類型也是單位元組的,如果處理UNICODE或編碼轉換時,還得使用其他的庫,也需要來迴轉換,而且,用Ruby Tk編寫控制介面時,在Linux上顯示中文的問題就搞得我頭疼不已。這是不是說,像Ruby這樣的指令碼語言,如果把內部的字元類型改為UNICODE的,就會對國際化功能支援得更好,就會被更多的人接受呢?或者說,以後出現的解釋型指令碼語言(動態語言?),都應該使用類似Java的機制呢?
回到C++上來。我發現C++本身的國際化功能有限以後,就開始尋找好用的類庫。我先去查了查Boost,發現Boost裡沒有太多相關的東西,唯一一個對我有用的類庫Date-Time還實現得非常糟糕,Boost中的Date-Time支援的年代範圍非常有限,還只實現了格列高裡改曆後的現代曆法(Gregorian System),比起Java中的GregorianCalendar類和.NET中的System.Globalization.Calendar類族,差了太多太多。
隨後,我想起的是Apache的Xerces-C++,這個處理XML的類庫,當然應該支援編碼轉換和UNICODE編程。但翻了翻文檔,發現Xerces-C++畢竟只是個專用於XML處理的類庫,其中雖然有一些國際化支援,但缺少的東西更多。
然後,我就在IBM的網站上發現了Mark Davis的文章Forms of UNICODE(http://www-900.ibm.com/developerWorks/cn/unicode/utfencodingforms/index_eng.shtml),這篇東西真好,不僅講UNICODE基礎知識,還讓我找到了一個叫ICU的類庫。這個ICU現在是International Components for Unicode的縮寫,網址是
http://oss.software.ibm.com/icu/
然後我就特別高興地發現,Java中的國際化功能最早就是由ICU那幫人實現的(我以前怎麼沒發現呢?)。所以,現在的ICU類庫(包括C++和Java的版本)在介面上和Java API非常類似。ICU對各種編碼轉換的支援非常全面,還提供regular expression這樣實用的功能,ICU中的GregorianCalendar類可以提供和Java中的GregorianCalendar類大致相同的功能(我在http://www.csdnblog.net/wangyonggang/archive/2004/05/17/732.aspx中說過這些東西)。
哎呀哎呀,IBM真好,ICU不錯!我需要的功能都有,現在可以停止辛苦的尋找,研究研究ICU,編寫我的程式了。