C++ 无法将字符数组转换为具有utf-8字符的wstring

C++ 无法将字符数组转换为具有utf-8字符的wstring,c++,visual-c++,utf-8,wstring,C++,Visual C++,Utf 8,Wstring,当我尝试在VisualC++中使用以下函数将char *转换为WStk时,该函数能够用正常的英语语言转换字符串,但是当我使用其他语言的字符时,它不转换所有字符。 std::wstring s2ws(const char* utf8Bytes) { const std::string& str(utf8Bytes); int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(),

当我尝试在VisualC++中使用以下函数将char *转换为WStk时,该函数能够用正常的英语语言转换字符串,但是当我使用其他语言的字符时,它不转换所有字符。
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);
    .....
}
map getAllFiles(wstring文件夹,wstring过滤器){
wstring directory=folder+L“/”过滤器;
WCHAR szBuf[MAX_PATH];
WIN32_查找_数据d;
HANDLE hFindFile=FindFirstFile(directory.c_str(),&d);
.....
}

这里我没有得到预期的输出。i、 例如,目录的内容。但是,当utf8bytes数组是普通英文字符时,就得到了它。

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

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

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

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

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

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

我认为您的代码做的是正确的,问题一定出在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");

我认为你的代码做的是正确的,问题一定是你的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");

与您的问题无关,但为什么
const std::string&str(utf8Bytes)
而不是“natural”
std::string str=utf8Bytes?为什么临时
str
变量不需要呢。您可以只使用
utf8bytes
strlen(utf8bytes)
(UTF-8编码字符永远不会包含零字节)。您如何检查转换?我这样问是因为这可能是错误的来源。如果
utfBytes
被终止(当然最好是终止,因为您正在使用的
std::string
的转换构造函数需要它),您只需将它和长度的
-1
传递给MB2WC即可。它将转换为(并通过)终止的nullchar。简而言之,您根本不需要str,甚至可以避免strlen。为了更好地隔离问题,请将两个字符串都打印为十六进制字符序列。@KrishnakumarCN调用
s2ws()
的代码是什么样子的?输入数据究竟来自哪里?你确定输入数据是用UTF-8编码的吗?您描述的故障表明输入数据没有用UTF-8编码。这与您的问题无关,但是为什么
const std::string&str(utf8Bytes)
而不是“natural”
std::string str=utf8Bytes?为什么临时
str
变量不需要呢。您可以只使用
utf8bytes
strlen(utf8bytes)
(UTF-8编码字符永远不会包含零字节)。您如何检查转换?我这样问是因为这可能是错误的来源。如果
utfBytes
被终止(当然最好是终止,因为您正在使用的
std::string
的转换构造函数需要它),您只需将它和长度的
-1
传递给MB2WC即可。它将转换为(并通过)终止的nullchar。简而言之,您根本不需要str,甚至可以避免strlen。为了更好地隔离问题,请将两个字符串都打印为十六进制字符序列。@KrishnakumarCN调用
s2ws()
的代码是什么样子的?输入数据究竟来自哪里?你确定输入数据是用UTF-8编码的吗?您描述的故障表明输入数据未以UTF-8编码。
CP\u ACP
!=<代码>CP\U UTF8
。如果输入为UTF-8,请勿使用
CP\u ACP
。如果输入不是UTF-8,请不要使用
CP\u UTF8
,输入参数的命名会产生误导。根据描述,此解决方案很好,但正如@Remy所说,参数名称应该从
utf8Bytes
更改为其他名称(如
ansiBytes
)。您将在
ACP
(=活动代码页)中获得值,该窗口几乎从来都不是UTF8窗口。(您可以启用UTF8作为代码页,但是
CP\u ACP
仍然可以正常工作)。
CP\u ACP
!=<代码>CP\U UTF8
。如果输入为UTF-8,请勿使用
CP\u ACP
。如果输入不是UTF-8,请不要使用
CP\u UTF8
,输入参数的命名会产生误导。根据描述,此解决方案很好,但正如@Remy所说,参数名称应该从
utf8Bytes
更改为其他名称(如
ansiBytes
)。您将在
ACP
(=活动代码页)中获得值,该窗口几乎从来都不是UTF8窗口。(您可以启用UTF8作为代码页,但是
CP\u ACP
仍然可以正常工作)。