跨平台C++軟體開發中,由於不同作業系統對Unicode的支援差異,而導致的一些問題及解決方案。

來源:互聯網
上載者:User

1.  問題的提出。

    各種各樣的編碼永遠是軟體開發人員最為頭痛的問題之一,Unicode為統一編碼帶來了希望。可是,就算是Unicode也不是百分百的完美,它只是完成了對各種語言編碼的制定,而在具體的作業系統支援上,又分為UTF8,UTF16和UTF32好幾個版本。比如,Windows系統支援的Unicode是UTF16,也就是每2個位元組表示一個字元(還有一種稱為代理的情況,容後討論)。而Linux下預設支援的卻是UTF32的Unicode標準,每4個位元組才表示一個字元。

2.  執行個體說明

     想象一下,假設您在Windows 系統下開發了一個軟體,將一些文本資料用Unicode(UTF16)編碼儲存到一個檔案,現在由於業務需要,您想將這個程式在Linux平台跑起來,會發生什麼情況呢?

     一般來說,您的代碼在處理字串資源時,會使用C/C++標準庫的wchar_t數組或者std::wstring來儲存字串,使用wstrcpy,wstrlen或者std::string類提供的成員函數處理字串,然後使用wfprintf或者std::wfstream進行字串的讀寫。這部分代碼好像沒有問題,標準的C/C++ 函數,在整個軟體移植時都不用修改。是的,代碼詞法和文法確實都沒有問題,編譯也能夠通過。可是,程式啟動並執行結果呢?根據上面的討論,wchar_t在Windows平台下,,每個字元2個位元組;而在linux平台下,每個字元4個位元組。如果您的某個使用者在Windows平台下儲存一個字串“Hello”到某個檔案,然後另一個使用者在Linux下開啟這個檔案,那麼,他所得到會是什麼呢?
    Windows平台下用Unicode(UTF16)編碼儲存“Hello“到檔案,實際寫入的16進位串如下所示
     H         e         l          l          o
    4800    6500   6C00  6C00  6F00
    形成一個串,00480065006C006C006F,寫入檔案。
    在Linux系統下,程式將這個串當作UTF32讀入後,結果是兩個字元(最後2個位元組6F00被捨棄)
    0x00650048和0x006C006C,字串長度是2,這顯然不是希望的到的“Hello“。

3.  解決的辦法
  
    根據個人的經驗,解決方案主要有以下2種:

    1.  由於產生平台不相容的主要原因是平台之間使用的Unicode方案不統一,一個最為顯而易見的解決辦法就是選擇使用某種作業系統的編碼,在另一個平台上,使用自己的字串儲存和操作函數。一般推薦使用UTF16,具體原因請參考本人關於UTF16和UTF32的比較。決定好使用的編碼方案後,還需要定義相應的操作函數,如字串拷貝函數,比較函數等。一個偷懶的辦法是把VC crt的部分代碼Copy出來,什麼wstrcpy,wstrlen,一個也不放過。在程式中進行字串處理和存取時使用自己定義的方法,就可以避免平台差異帶來的問題了。
    而且,選擇這種方案的一個更為重要的原因是,這個解決方案已經有大量的Open Source軟體庫可以直接使用,比如ICU(International Component for Unicode),libiconv等。

    2.  避開UTF16和UTF32,直接使用UTF8進行字串的處理,因為各個平台對於UTF8的處理都是完全相同的。而且,UTF8和UTF16和UTF32使用的編碼完全一樣,只是記憶體表示的差異,有成熟的演算法可以實現這3種編碼的直接轉換.以下是www.unicode.org官方的轉碼串連:http://www.unicode.org/Public/PROGRAMS/CVTUTF/。
        當然,這種做法也有一定的不利因素,因為UTF8本身是一種可變長的編碼方案,對於常見的英文,使用一個位元組,對於中文,一般是3個位元組。這種可變長的字元編碼給一些操作帶來不便。如取某個字串的子串,就必須從頭開始做遍曆,然後一個一個字元進行計算,直到長度達到要求。而如果使用UTF16或者UTF32,簡單的對數組進行索引就可以了(不考慮UTF16的代理機制,常見文字不會用到)。

        關於UTF8,UTF16,UTF32的詳細討論可以參考www.unicode.org,也可以參考本人blog編碼檔案夾下的一些介紹性文字。

4.  參考文檔
    www.unicode.org,本文提及的所有資料都可以在unicode.org上找到。
    http://oss.software.ibm.com/icu/,IBM的開源Unicode實現,可以完全替代作業系統提供的與編碼和國際化相關的功能。
    http://www.gnu.org/software/libiconv/, GNU的Unicode實現,整合在Linux作業系統中,但是庫本身跨平台。
   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.