在C++中将UTF-8转换为ANSI

3

我无法在任何地方找到这个问题的答案。

如何在C++中将一个字符串从UTF-8转换为ANSI(扩展ASCII)?


6
“扩展ASCII”并不存在。如果您不理解这一点,那么您可能难以理解文本编码的细节。您可以阅读这篇经常被引用的文章来获得更多信息。 - undefined
1
@KerrekSB 嗯,要转换为ISO 8859-1编码吗? - undefined
1
好的,更好。回答:使用 iconv。或者 uconv - undefined
1
@KerrekSB:我认为更准确地说,基本上 所有 的东西都是“扩展ASCII”——ISO 8859、ISO 10646、Unicode、ShiftJIS等等,都可以说是具有各种扩展的ASCII。主要问题在于每个扩展与大多数(或者全部?)其他扩展不兼容。 - undefined
@KerrekSB 严格来说,"ANSI" 并没有这样的编码方式。 - undefined
3个回答

6
一般来说,人们使用可在大多数平台上运行的便携式库libiconv (网页)。正如KerrekSB所提到的,如果您将字符集视为“扩展ASCII”,那么您将遇到严重的问题 - 我敢肯定有至少一百个可以称为“扩展ASCII”的字符集,包括UTF-8。
此外,请确保您知道要使用哪种编码:ISO-8859-1还是CP1252。Windows版本会用其他可打印字符替换C1控制码。

6

仅适用于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;
}

这在Visual Studio 2015 C++下运行良好,谢谢! - undefined

3
假设你所说的“ANSI”其实是ISO 8859的变体之一,我们需要从以下几点开始讲解。第一点是并非每个字符串都能从UTF-8(或无论使用哪种转换方式的Unicode)转换为ISO 8859。Unicode几乎包含了地球上所有语言中每个字符的唯一码点。ISO 8859支持的语言要少得多,并且对于它支持的每种语言,都有一个单独的字符集;同样的代码在不同的语言中表示不同的字符。这意味着,在UTF-8输入字符串中很容易包含根本无法用任何ISO 8859变体表示的字符,也很容易包含需要不同的ISO 8859变体来表示的字符。第二点是,即使在最佳情况下,转换可能也相当复杂。如果可能的话,你几乎肯定想使用库(例如libiconv)来完成此任务。例如,Unicode有一个名为“组合变音标记”的功能,它允许你将像带“锐音符A”这样的内容编码为单个代码点或两个分离的代码点(一个代表“A”,另一个代表变音符)。要在ISO 8859中对其进行编码,你需要将它们全部转换为一种形式(通常是预组合的形式)。 在处理Unicode之前,你通常还需要将UTF-8转换为UCS-4。因此,步骤应该是这样的:1. 将UTF-8转换为UCS-4;2. 将组合变音标记转换为带有变音标记的字母(可能是NFKC);3. 检查所有字符是否都能在目标字符集中编码;4. 转换为目标字符集。根据你喜欢处理事情的方式,你可以将步骤3和4合并为单个步骤,在进行转换时进行字符转换,例如在遇到无法用目标字符集表示的字符时抛出异常。

有一些库可以进行规范化,但似乎在这些情况下,UTF-16比UTF-32更常见。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接