天天看點

MultiByteToWideChar和WideCharToMultiByte用法詳解, ANSI和UNICODE之間的轉換

//========================================================================

//TITLE:

//    MultiByteToWideChar和WideCharToMultiByte用法詳解

//AUTHOR:

//    norains

//DATE:

//    第一版:Monday  25-December -2006

//    增補版:Wednesday 27-December -2006

//    修訂版:Wednesday 14-March-2007 (修正之前的錯誤例子)

//Environment:

//  EVC4.0 + Standard SDK

1.使用方法詳解

  在本文開始之處,先簡要地說一下何為短字元和寬字元.

  所謂的短字元,就是用8bit來表示的字元,典型的應用是ASCII碼.而寬字元,顧名思義,就是用16bit表示的字元,典型的有UNICODE.關于windows下的ASCII和UNICODE的更多資訊,可以參考這兩本經典著作:《windows 程式設計》,《windows 核心程式設計》.這兩本書關于這兩種字元都有比較詳細的解說.

  寬字元轉換為多個短字元是一個難點,不過我們隻要掌握到其中的要領,便可如魚得水.

  好吧,那就讓我們開始吧.

  這個是我們需要轉化的多位元組字元串:  

  char sText[20] = {"多位元組字元串!OK!"};

  我們需要知道轉化後的寬字元需要多少個數組空間.雖然在這個裡程裡面,我們可以直接定義一個20*2寬字元的數組,并且事實上将運作得非常輕松愉快.但假如多位元組字元串更多,達到上千個乃至上萬個,我們将會發現其中浪費的記憶體将會越來越多.是以以多位元組字元的個數的兩倍作為寬字元數組下标的聲明絕對不是一個好主意.

  所幸,我們能夠确知所需要的數組空間.

  我們隻需要将MultiByteToWideChar()的第四個形參設為-1,即可傳回所需的短字元數組空間的個數:

  DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, sText, -1, NULL, 0);

  接下來,我們隻需要配置設定響應的數組空間:

  wchar_t *pwText;

  pwText = new wchar_t[dwNum];

  if(!pwText)

  {

   delete []pwText;

  }

  接着,我們就可以着手進行轉換了.在這裡以轉換成ASCII碼做為例子:

  MultiByteToWideChar (CP_ACP, 0, psText, -1, sText, dwSize);

  最後,使用完畢當然要記得釋放占用的記憶體:

  delete []psText;

  同理,寬字元轉為多位元組字元的代碼如下:  

  wchar_t wText[20] = {L"寬字元轉換執行個體!OK!"};

  DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);

  char *psText;

  psText = new char[dwNum];

  if(!psText)

   delete []psText;

  WideCharToMultiByte (CP_OEMCP,NULL,lpcwszStr,-1,psText,dwNum,NULL,FALSE);

   如果之前我們已經配置設定好空間,并且由于字元串較短,可以不理會浪費的空間,僅僅隻是想簡單地将短字元和寬字元互相轉換,那有沒有什麼簡便的方法呢?

   WIN32 API裡沒有符合這種要求的函數,但我們可以自己進行封裝:

  //-------------------------------------------------------------------------------------

  //Description:

  // This function maps a character string to a wide-character (Unicode) string

  //

  //Parameters:

  // lpcszStr: [in] Pointer to the character string to be converted 

  // lpwszStr: [out] Pointer to a buffer that receives the translated string. 

  // dwSize: [in] Size of the buffer

  //Return Values:

  // TRUE: Succeed

  // FALSE: Failed

  // 

  //Example:

  // MByteToWChar(szA,szW,sizeof(szW)/sizeof(szW[0]));

  //---------------------------------------------------------------------------------------

  BOOL MByteToWChar(LPCSTR lpcszStr, LPWSTR lpwszStr, DWORD dwSize)

    // Get the required size of the buffer that receives the Unicode 

    // string. 

    DWORD dwMinSize;

    dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);

    if(dwSize < dwMinSize)

    {

     return FALSE;

    }

    // Convert headers from ASCII to Unicode.

    MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, lpwszStr, dwMinSize);  

    return TRUE;

  // This function maps a wide-character string to a new character string

  // lpcwszStr: [in] Pointer to the character string to be converted 

  // lpszStr: [out] Pointer to a buffer that receives the translated string. 

  // WCharToMByte(szW,szA,sizeof(szA)/sizeof(szA[0]));

  BOOL WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize)

   DWORD dwMinSize;

   dwMinSize = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);

   if(dwSize < dwMinSize)

   {

    return FALSE;

   }

   WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,lpszStr,dwSize,NULL,FALSE);

   return TRUE;

  使用方法也很簡單,示例如下:

  wchar_t wText[10] = {L"函數示例"};

  char sText[20]= {0};

  WCharToMByte(wText,sText,sizeof(sText)/sizeof(sText[0]));

  MByteToWChar(sText,wText,sizeof(wText)/sizeof(wText[0]));

注意紅顔色表示的部分,需要用的自己做測試  

  這兩個函數的缺點在于無法動态配置設定記憶體,在轉換很長的字元串時可能會浪費較多記憶體空間;優點是,在不考慮浪費空間的情況下轉換較短字元串非常友善.

2.MultiByteToWideChar()函數亂碼的問題

  有的朋友可能已經發現,在标準的WinCE4.2或WinCE5.0 SDK模拟器下,這個函數都無法正常工作,其轉換之後的字元全是亂碼.及時更改MultiByteToWideChar()參數也依然如此.

  不過這個不是代碼問題,其結症在于所定制的作業系統.如果我們定制的作業系統預設語言不是中文,也會出現這種情況.由于标準的SDK預設語言為英文,是以肯定會出現這個問題.而這個問題的解決,不能在簡單地更改控制台的"區域選項"的"預設語言",而是要在系統定制的時候,選擇預設語言為"中文".

  系統定制時選擇預設語言的位置于:

  Platform -> Setting... -> locale -> default language ,選擇"中文",然後編譯即可.