C++實現unicode碼轉換成UTF-16的加碼和解碼函數

來源:互聯網
上載者:User

         Unicode的實現方式不同於編碼方式。一個字元的Unicode編碼是確定的,但是在實際儲存和傳輸過程中,由於不同系統平台的設計不一定一致,以及出於節省空間的目的,對Unicode編碼的實現方式有所不同。Unicode的實現方式稱為Unicode轉換格式(UnicodeTransformation Format,簡稱為UTF)。

         對Unicode編碼的主要有UTF-16BE、UTF-16LE、UTF-8、UTF-7以及UTF-32等實現方式,目前常用的實現方式是UTF-16LE、UTF-16BE和UTF-8。

UTF-16

        UTF-16是用16bit編碼來表達Unicode,這樣表達範圍是216(即65536),也就是UTF-16的代碼單元(Code Unit)為16bits。如果表達BMP內的字元,用一個UTF-16的CodeUnit就可表達,對於輔助平面內的字元,UTF-16有巧妙的設計。

        落在BMP內,從U+D800到U+DFFF之間的Code Point區段是持續保留不映射到字元, UTF-16利用這保留下來的0xD800-0xDFFF區段的CodePoint來對輔助平面內的字元的Code Point進行編碼。

 

對U+0000.. U+D7FF以及U+E000.. U+FFFF的編碼

        UTF-16與UCS-2對這個範圍內的CodePoint進行編碼,採用單個16bit長的CodeUnit,數值等價於對應的Code Point。BMP中的這些Code Point是僅有的可以被UCS-2表示的Code Point。

對U+10000.. U+10FFFF的編碼

        輔助平面(Supplementary Planes)中的CodePoint,在UTF-16中被編碼為一對16bit長的Code Unit(即32bit,4Bytes),稱作代理對(surrogatepair)。

 

 

具體方法是:

  1. Code Point減去0x10000, 得到的值是長度為20bit(0..0xFFFFF);
  2. 步驟1得到數值的高位的10位元的值(值範圍為0..0x3FF)被加上0xD800得到第一個Code Unit或稱作高位代理(high surrogate)或前置代理(lead surrogate)。取值範圍是0xD800..0xDBFF。
  3. 步驟1得到數值的低位的10位元的值(值範圍為0..0x3FF)被加上0xDC00得到第二個Code Unit或稱作低位代理(low surrogate)或後尾代理(trail surrogate)。取值範圍是0xDC00..0xDFFF。

       這樣,這個範圍內的字元就被編碼成了一個代理對[leadsurrogate,trail surrogate]:兩個16bits的Code Unit,取值範圍分別是0xD800..0xDBFF和0xDC00..0xDFFF。而BMP中得到的Code Unit的範圍是0x0000..0xFFFF(0xD800..0xDFFF是保留的,不包含其中),所以這三個區段是相互不重疊的,在解碼時很容易實 現。

 

UTF-16解碼

hi \ lo

DC00

DC01

   …   

DFFF

D800

10000

10001

103FF

D801

10400

10401

107FF

  ⋮

DBFF

10FC00

10FC01

10FFFF

 

 

 

 

 

 

 

下面以對U+64321的UTF-16編碼為例,看一下對於輔助平面內的字元是如何編碼的:

V  = 0x64321Vx = V - 0x10000     = 0x54321     = 01010100 0011 0010 0001 Vh = 01 0101 0000 // Vx 的高位部份的 10 bitsVl  = 11 0010 0001 // Vx 的低位部份的 10 bitsw1 = 0xD800           // 結果的前16位元初始值w2 = 0xDC00          // 結果的後16位元初始值 w1 = w1 | Vh   = 1101 1000 0000 0000     |             01 0101 0000   = 1101 1001 0101 0000   = 0xD950 w2 = w2 | Vl   = 1101 1100 0000 0000    |              11 0010 0001   = 1101 1111 0010 0001   = 0xDF21

所以,這個字 U+64321 最終的 UTF-16 編碼是:

0xD950 0xDF21

以下是據此而寫的c++加碼與解碼的函數:

//unicode BMP之外字元  轉換成UTF-16 加碼函數//DWORD v      為字元的UNICODE編碼  編碼值大於0XFFFF//WORD & w1    為轉換成UTF-16後的    低位代理對//WORD & w2    為轉換成UTF-16後的    高位代理對void EnCode(DWORD v,WORD &w1,WORD &w2){DWORD vx=v-0x10000;WORD vh=(vx&0xFFC00)>>10;WORD vl=vx&0x03FF;w1=0xD800;w2=0xDC00;w1=w1|vh;w2=w2|vl;}

// UTF-16  轉換成unicode編碼的      解碼函數//DWORD v      為解碼後的字元的UNICODE編碼  編碼值大於0XFFFF//WORD & w1    UTF-16的                     低位代理對//WORD & w2    UTF-16的                     高位代理對void DeCode(DWORD &w, WORD &w1, WORD &w2){w1=w1&0x3FF;w2=w2&0x3FF;w=w1<<10;w=w|w2;w+=0x10000;}

應用舉例:

(1)加碼

WCHAR str[3]; //表示一個字元memset(str,0,3*sizeof(WCHAR));dw=0x64321;  //該字元的unicode編碼位於BMP之外WORD w1,w2;EnCode(dw,w1,w2);str[0]=w1;str[1]=w2;str[3]=0;

(2)解碼

DWORD dw=0;WORD w1,w2;w1=str[0];w2=str[1];         //w2!=0  否則即為BMP之內的碼DeCode(dw,w1,w2);  //dw 為UTF-16 所對應的unicode碼值

參考資料:

http://blog.csdn.net/thl789/article/details/7506133

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.