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

Convert UTF-8 to ANSI in C++

本文关键字:ANSI 转换 UTF-8 c++ 中将      更新时间:2023-10-16

我到处都找不到这个问题的答案。

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

一般使用libiconv(网页),它是可移植的,可以在大多数平台上运行。正如KerrekSB所提到的,如果你认为一个字符集是"扩展ASCII",你会陷入大麻烦——我敢肯定至少有100个字符集可以被称为"扩展ASCII",包括UTF-8。

另外,确保您知道您想要哪种编码:ISO-8859-1或CP1252。Windows版本用额外的打印字符替换C1控件代码。

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;
}

假设你所说的"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组合成一个步骤,在进行过程中转换字符,例如,如果遇到无法在目标字符集中表示的字符,则抛出异常。