2011-11-28 123 views
1

我無法在任何地方找到對此問題的答案。在C++中將UTF-8轉換爲ANSI

如何在C++中將字符串從UTF-8轉換爲ANSI(擴展ASCII)?

+6

有 「擴展ASCII」 沒有這樣的事。如果你不明白這一點,你將很難理解文本編碼的更精細的點。您可能想閱讀[這篇經常引用的文章](http://www.joelonsoftware.com/articles/Unicode.html)。 –

+1

@KerrekSB那麼,根據ISO 8859-1? – Damian

+1

好的,更好。答案:使用'iconv'。或'uconv'。 –

回答

6

通常,使用libiconv(webpage),它是可移植的並可在大多數平臺上運行。正如KerrekSB所提到的,如果將字符集想象爲「擴展ASCII」,則會遇到很大麻煩 - 我確定至少有一百個字符集可以稱爲「擴展ASCII」,包括UTF-8。

此外,請確保您知道您想要的編碼:ISO-8859-1或CP1252。 Windows版本將C1控制代碼替換爲其他打印​​字符。

2

假設通過「ANSI」您確實是指ISO 8859變體之一,我們應該從幾點開始。

首先,不是每個字符串都可以從UTF-8(或通用Unicode,無論使用何種轉換)轉換爲ISO 8859. Unicode對於地球上每種語言中的幾乎每個字符都具有唯一的代碼點。

ISO 8859支持的語言少得多,並且它支持的每種語言都有單獨的字符集;相同的代碼表示不同語言中的不同字符。

這意味着UTF-8輸入字符串很容易包含無法在任何ISO 8859變體中表示的字符,而且它也容易包含需要不同ISO 8859變體的字符來表示。

第二個是,即使在最好的情況下,轉換可能是相當不平凡的。如果可能的話,你幾乎可以肯定地希望爲這個任務使用一個庫(例如,libiconv)。舉個例子,Unicode有一個名爲「組合變音符號」的特徵,它可以讓你編碼像「A with acute accent」這樣的單個代碼點兩個獨立的代碼點(一個用於「A 「另一個是口音)。要在ISO 8859中對其進行編碼,您必須將這些全部轉換爲一種形式(通常是預先組合的形式)。

在使用Unicode做任何重要的工作之前,通常還需要將UTF-8轉換爲UCS-4。

因此,順序是這樣的:

  1. 轉換UTF-8到UCS-4
  2. 轉換變音符號相結合,用變音標記(可能NFKC)的信件。
  3. 檢查所有的字符可以在目標字符編碼集
  4. 轉換到目標設定

取決於你喜歡做事情的方式,你可能會結合3和4到一個步驟,隨時轉換字符,例如,如果遇到不能在目標字符集中表示的字符,則拋出異常。

+0

有一些庫可以執行規範化,但爲了這些目的,似乎UTF-16比UTF-32更常見。 –

0

僅適用於Windows:

string UTF8ToANSI(string s) 
{ 
    BSTR bstrWide; 
    char* pszAnsi; 
    int  nLength; 
    const char *pszCode = s.c_str(); 

    nLength = MultiByteToWideChar(CP_UTF8, 0, pszCode, strlen(pszCode) + 1, NULL, NULL); 
    bstrWide = SysAllocStringLen(NULL, nLength); 

    MultiByteToWideChar(CP_UTF8, 0, pszCode, strlen(pszCode) + 1, bstrWide, nLength); 

    nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL); 
    pszAnsi = new char[nLength]; 

    WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, pszAnsi, nLength, NULL, NULL); 
    SysFreeString(bstrWide); 

    string r(pszAnsi); 
    delete[] pszAnsi; 
    return r; 
}