4

我有一個UTF-16字符串,它包含了一些字符在我的本地Windows-1252代碼頁不是直接表示的:如何獲得最佳的編碼之間配合的Unicode字符映射

6/23/2011 9:23:44 ᴀᴍ 

我使用WideCharToMultiByte的字符串轉換爲本地代碼頁(Windows的1252我的北美電腦上):

WideCharToMultiByte(
    CP_ACP, //target CodePage 
    0,  //flags 
    Source, //my string, e.g. "6/23/2011 9:23:44 ᴀᴍ" 
    length, //length in characters, e.g. 20 
    buffer, //destination where to put the string 
    bufferSize, 
    null, //optional, character to use when character cannot be represented 
    null); //optional, out boolean that indicates if any character could not be represented 

和字符串出來爲:

6/23/2011 9:23:44 ?? 

字面上帶有問號0x3f = "?"表示不可表示的字符。

當你看到在原來的字符串 「ᴀᴍ」 字符,這兩個人物是:

  • U + 1D00:拉丁文字母小型大寫A
  • U + 1D0D:拉丁字母小Capital M

unicode標準說these are phonetic extensions, and for general text: use regular Latin。這對我來說意味着文本應轉換爲兩種:

6/23/2011 9:23:44 AM 

6/23/2011 9:23:44 am 

另一個例子是6′2″

  • U + 2032:總理
  • U + 2033:Double Prime

當我將該字符串轉換爲Windows-1252它變成6'2?(撇號,?)。

Unicode entry for Prime列表撇號作爲替代:

2032 ′ PRIME 
      = minutes, feet 
      → 0027 ' apostrophe 
      → 00B4 ´ acute accent 
      → 02B9 ʹ modifier letter prime 

即使不會在目標代碼頁存在,WideChartoMultiByte將其轉換爲最接近的等同物中的一個(即撇號)。

在另一方面兩撇

2033 ″ DOUBLE PRIME 
      = seconds, inches 
      → 0022 " quotation mark 
      → 02BA ʺ modifier letter double prime 
      → 201D 」 right double quotation mark 
      ≈ 2032 ′ 2032 ′ 

被映射到什麼(?),但在我的Windows-1252編碼的一些其他項目的存在:

Character         Unicode Windows-1252 
========================================= ======= ============ 
″ double prime       U+2032  - 
" quotation mark       U+0022  0x22 
ʺ modifier letter double prime   U+02BA  - 
」 right double quotation mark    U+201D  0x94 

′ prime         U+2032  - 
' apostrophe        U+0027  0x27 
´ acute accent       U+00B4  0xb4 
ʹ modifier letter prime     U+02B9 

即使在最壞的情況下,它分解原來的double primeprimeprime:素有一個等價物 - 因爲它alre ady使用它。

對於其他角色也有映射:

Character         Unicode Windows-1252 
========================================= ======= ============ 
ᴀ Latin Letter Small Capital A   U+1D00  - 
A Latin Capital Letter A     U+0041  0x41 
a Latin Small Letter A     U+0061  0x61 

ᴍ Latin Letter Small Capital M   U+1D0D  - 
M Latin Capital Letter M     U+004D  0x4d 
m Latin Small Letter M     U+006D  0x6d 

如何使WideChartoMultiByte做編碼之間的最佳匹配映射?

+0

一個非常精通的問題! –

回答

1

我不認爲你可以改變WideCharToMultiByte()的結果。如果你足夠小心嘗試不同的解決方案ICU可能會給你不同的結果。個人而言,我沒有嘗試過,所以我不能保證結果(誰需要從Unicode轉換,不管怎麼樣?),但我相信你應該運用ICU Converters。關於它的好處是支持Unicode 6.0(反正你可能不需要)。

+0

*接受*無法做到*。我真的不想讓我的軟件有一個DLL,以獲得一個函數的行爲。 –

+1

@伊恩博伊德:你可以做到;這只是Windows不能爲你做的。您可以編寫一個預處理器,在將其傳遞給WideCharToMultibyte之前執行回退替換。它需要一個從Unicode字符數據庫構建的稀疏表格,這是一個簡單的下載。 –

1

WideCharToMultiByte的性能可能取決於您使用的Windows版本。我相信新版本使用更完整的表格。不過,它可能不會涵蓋所有的情況。由於Windows本來就傾向於使用Unicode,因此他們沒有太多的動機來爲那些無數的代碼頁實現所有的後備案例。

您的選擇是使用庫(如其他人提到的ICU)或構建自己的預處理器來處理回退。

1

如果您知道您的目標編碼,則可以使用Posix標準化的iconv庫(也可用於Windows),並從WCHAR_T或UTF-16轉換爲您的目標編碼; iconv有一個「音譯」選項,可以將你的所有特殊需要字符轉換爲ASCII音譯。 Iconv比ICU輕了一些,並且相當普遍。

相關問題