【问题标题】:Convert UTF-8 to ANSI in C++在 C++ 中将 UTF-8 转换为 ANSI
【发布时间】:2012-01-08 01:03:41
【问题描述】:

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

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

【问题讨论】:

  • 没有“扩展ASCII”之类的东西。如果你不理解这一点,你将很难理解文本编码的细节。您可能想阅读this often cited article
  • @KerrekSB 好吧,符合 ISO 8859-1 标准?
  • 好的,更好。答:使用iconv。或uconv.
  • @KerrekSB:我认为更准确地说,everything 本质上是“扩展的 ASCII”——ISO 8859、ISO 10646、Unicode、ShiftJIS 等是 all 基本上是带有各种扩展的 ASSII。主要问题是每个扩展都与其他大多数(全部?)不兼容。
  • @KerrekSB 严格来说,也没有像“ANSI”这样的编码。

标签: c++ utf-8 character-encoding ascii


【解决方案1】:

一般来说,使用 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”之类的东西编码为单个代码点 两个单独的代码点(一个用于“A”,另一个用于重音)。要在 ISO 8859 中对其进行编码,您必须将它们全部转换为一种形式(通常是预先组合的形式)。

    在使用 Unicode 进行任何重要工作之前,通常还需要将 UTF-8 转换为 UCS-4。

    所以,顺序应该是这样的:

    1. 将 UTF-8 转换为 UCS-4
    2. 将组合变音符号转换为带变音符号的字母(可能是 NFKC)。
    3. 检查是否所有字符都可以编码到目标字符集中
    4. 转换为目标集

    根据您喜欢做事的方式,您可以将 3 和 4 组合到一个步骤中,随时转换字符,例如,如果遇到无法在目标字符集。

    【讨论】:

    • 有些库可以进行规范化,但在这些方面,UTF-16 似乎比 UTF-32 更常见。
    【解决方案3】:

    仅限 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++ 下运行良好,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2023-03-19
    • 2013-12-14
    • 2015-11-22
    • 2017-07-21
    • 2019-02-10
    • 1970-01-01
    • 2015-10-06
    • 2010-11-30
    相关资源
    最近更新 更多