【问题标题】:How to convert UTF8 char array to Windows 1252 char array如何将 UTF8 字符数组转换为 Windows 1252 字符数组
【发布时间】:2018-04-06 16:42:18
【问题描述】:

我是 C++ 的菜鸟,所以我很抱歉提出愚蠢的问题。

我有一段文字:Павло

我在我正在处理的一段代码中从控制台输出的某个地方得到它。我知道这是隐藏在它背后的西里尔字母。它的真正价值是“Петро”。

使用在线编码检测器,我发现要正确阅读此文本,我必须将其从 UTF-8 转换为 Windows 1252。

我怎样才能用代码做到这一点?

我已经尝试过了,它给出了一些结果,但它输出了 5 个问号(至少预期长度)

    wchar_t *CodePageToUnicode(int codePage, const char *src)
{
    if (!src) return 0;
    int srcLen = strlen(src);
    if (!srcLen)
    {
        wchar_t *w = new wchar_t[1];
        w[0] = 0;
        return w;
    }

    int requiredSize = MultiByteToWideChar(codePage,
        0,
        src, srcLen, 0, 0);

    if (!requiredSize)
    {
        return 0;
    }

    wchar_t *w = new wchar_t[requiredSize + 1];
    w[requiredSize] = 0;

    int retval = MultiByteToWideChar(codePage,
        0,
        src, srcLen, w, requiredSize);
    if (!retval)
    {
        delete[] w;
        return 0;
    }

    return w;
}

char *UnicodeToCodePage(int codePage, const wchar_t *src)
{
    if (!src) return 0;
    int srcLen = wcslen(src);
    if (!srcLen)
    {
        char *x = new char[1];
        x[0] = '\0';
        return x;
    }

    int requiredSize = WideCharToMultiByte(codePage,
        0,
        src, srcLen, 0, 0, 0, 0);

    if (!requiredSize)
    {
        return 0;
    }

    char *x = new char[requiredSize + 1];
    x[requiredSize] = 0;

    int retval = WideCharToMultiByte(codePage,
        0,
        src, srcLen, x, requiredSize, 0, 0);
    if (!retval)
    {
        delete[] x;
        return 0;
    }

    return x;
}
int main()
{
    const char *text = "Павло";

    // Now convert utf-8 back to ANSI:
    wchar_t *wText2 = CodePageToUnicode(65001, text);

    char *ansiText = UnicodeToCodePage(1252, wText2);
    cout << ansiText;
    _getch();

}

也试过了,还是不行

int main()
{
    const char *orig = "Павло";
    size_t origsize = strlen(orig) + 1;
    const size_t newsize = 100;
    size_t convertedChars = 0;
    wchar_t wcstring[newsize];
    mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
    wcscat_s(wcstring, L" (wchar_t *)");

    std::wstring strUTF(wcstring);

    const wchar_t* szWCHAR = strUTF.c_str();

    cout << szWCHAR << '\n';


    char *buffer = new char[origsize / 2 + 1];

    WideCharToMultiByte(CP_ACP, 0, szWCHAR, -1, buffer, 256, NULL, NULL);

    cout << buffer;
    _getch();
}

【问题讨论】:

  • @DanielWaechter 也许,但我太糟糕了,我无法重用该代码
  • 您必须做类似的事情或找到第三方库。这与标准 C++ 中的编码转换一样简单。
  • 第一个 sn-p 是错误的,因为它没有使用 WideCharToMultiByte() 进行第二个转换。第二个 sn-p 是错误的,因为它在已经以错误编码读取的字符串上使用了 mbstowcs()。追求第一个 sn-p。
  • ПавлоПавло(不是 Петро,应该是 Петро)的 UTF-8 编码形式,被误解为 Windows-1252。字节是相同的,因此只需将它们解释为 UTF-8。没有什么可以转换为 UTF-8,它已经是。如果您想将其转换为 UTF-16 以在 Win32 API 中使用,这是单独的问题。

标签: c++ unicode utf-8


【解决方案1】:

有几个选项

  1. 使用 Windows API

    使用MultiByteToWideChar 将您的UTF-8 转换为系统UTF-16LE,然后将WideCharToMultiByteUTF-16LE 转换为CP1251(西里尔字母是1251 而不是1252)

  2. 使用MS MLAGN API

  3. 使用GNU ICONV library

  4. 使用IBM ICU

如果您只是需要将您的 UNICODE 输出到控制台,请查看this

【讨论】:

    【解决方案2】:

    这是一个打印问题。你的第一个函数是正确的,你可以测试一下MessageBoxW

    wchar_t *wbuf = CodePageToUnicode(CP_UTF8, "Павло");
    if(wbuf)
    {
        MessageBoxW(0, wbuf, 0, 0);
        delete[]buf;
    }
    

    输出

    "Павло"(和你说的不一样!)

    您可以使用std::wcout打印宽字符,或使用1251代码页简化打印功能,如下所示:

    #include <iostream>
    #include <string>
    #include <Windows.h>
    
    int main()
    {
        char *buf = "Павло";
        int size;
    
        size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, 0, 0);
        std::wstring wstr(size, 0);
        MultiByteToWideChar(CP_UTF8, 0, buf, -1, &wstr[0], size);
    
        int codepage = 1251;
        size = WideCharToMultiByte(codepage, 0, &wstr[0], -1, 0, 0, 0, 0);
        std::string str(size, 0);
        WideCharToMultiByte(codepage, 0, &wstr[0], -1, &str[0], size, 0, 0);
    
        SetConsoleOutputCP(codepage);
        std::cout << str << "\n";
        return 0;
    }
    

    【讨论】:

    • 我实际上认为当我的字符串如下表示时它可以工作:L"\x043a\x043e\x0448\x043a\x0430"。你知道如何将常规字符串翻译成字符代码吗?
    • 在 Visual Studio 编辑器中使用 L"Петро" 和 UTF8 编码
    猜你喜欢
    • 2012-07-17
    • 2013-09-14
    • 2019-08-19
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 2013-09-12
    相关资源
    最近更新 更多