【问题标题】:Cannot convert character array to wstring with utf-8 characters无法将字符数组转换为带有 utf-8 字符的 wstring
【发布时间】:2019-02-19 01:28:12
【问题描述】:

当我尝试在 Visual C++ 中使用以下函数将 char* 转换为 wstring 时。该函数能够将字符串转换为普通英语语言,但是当我使用其他语言的字符时,它不会转换所有字符。

std::wstring s2ws(const char* utf8Bytes)
{
    const std::string& str(utf8Bytes);
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

示例: 当我将转换后的值打印到 MessageBox 时,Grüßen 显示为 Gr??en

我正在使用这个转换后的 wstring 来获取我的目录的内容,如下所示:

map<wstring, wstring> getAllFiles(wstring folder, wstring filter) {  
    wstring directory = folder + L"/" + filter;
    WCHAR szBuf[MAX_PATH];
    WIN32_FIND_DATA d;
    HANDLE hFindFile = FindFirstFile(directory.c_str(), &d);
    .....
}

在这里我没有得到预期的输出。即目录的内容。但是当 utf8bytes 数组是正常的英文字符时得到它。

【问题讨论】:

  • 与您的问题无关,但为什么const std::string&amp; str(utf8Bytes) 而不是“自然”std::string str = utf8bytes;?为什么首先是临时的str 变量,它是不需要的。您可以只使用utf8bytesstrlen(utf8bytes)(UTF-8 编码的字符永远不会包含零字节)。
  • 您如何检查转换?我问是因为这可能是错误错误的来源。
  • 如果utfBytes 被终止(当然更好,因为您使用的std::string 的转换构造函数需要它),您可以将它和-1 的长度传递给MB2WC .它将转换为(并通过)终止的 nullchar。总之,你根本不需要str,甚至可以避开strlen
  • 为了更好地隔离问题,将两个字符串打印为十六进制字符代码序列。
  • @KrishnakumarCN 调用s2ws() 的代码是什么样的?输入数据究竟来自哪里?你确定输入数据真的是用 UTF-8 编码的吗?您描述的失败表明输入数据未以 UTF-8 编码。

标签: c++ visual-c++ utf-8 wstring


【解决方案1】:

我认为您应该将代码更改为以下内容:

std::wstring s2ws(const char* utf8Bytes)
{
    const std::string& str(utf8Bytes);
    int size_needed = MultiByteToWideChar(CP_ACP, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_ACP, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

列出了两个标志之间的差异here

【讨论】:

  • CP_ACP != CP_UTF8。如果输入 IS UTF-8,请勿使用 CP_ACP。如果输入IS NOT UTF-8,请勿使用CP_UTF8,输入参数的命名会产生误导。
  • 根据描述这个解决方案很好,但正如@Remy所说,参数名称应该从utf8Bytes更改为其他名称(如ansiBytes)。您将获得ACP(= 活动代码页)中的值,它几乎从不是 UTF8 Windows。 (您可以启用 UTF8 作为您的代码页,但 CP_ACP 仍然可以正常工作)。
【解决方案2】:

我认为您的代码在做正确的事情,问题一定出在您的 UTF-8 字符串上。如果我这样调用你的代码,它会按预期工作:

char utf8buffer[1024];

WideCharToMultiByte(
    CP_UTF8,
    WC_ERR_INVALID_CHARS,
    L"Grüßen",
    -1,
    utf8buffer,
    1024,
    nullptr,
    false
);

assert(s2ws(utf8buffer) == L"Grüßen");

【讨论】:

    猜你喜欢
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 2011-06-25
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多