将日语 wstring 转换为 std::string

Convert Japanese wstring to std::string

本文关键字:std string 转换 日语 wstring      更新时间:2023-10-16

谁能建议一种将日语std::wstring转换为std::string的好方法?

我使用了下面的代码。日语字符串在英语操作系统上无法正确转换。

std::string WstringTostring(std::wstring str)
{
size_t size = 0;
_locale_t lc = _create_locale(LC_ALL, "ja.JP.utf8");
errno_t err = _wcstombs_s_l(&size, NULL, 0, &str[0], _TRUNCATE, lc);
std::string ret = std::string(size, 0);
err = _wcstombs_s_l(&size, &ret[0], size, &str[0], _TRUNCATE, lc);
_free_locale(lc);
ret.resize(size-1);
return ret;
}

wstring"C\files\ブ種別.pdf".

转换后的string"C:\files\ブ種別.pdf"

对我来说,它实际上看起来是正确的。

这是输入的 UTF-8 编码版本(在转换之前可能是 UTF-16(,但由于工具链中某处的错误,以 ASCII 解码形式显示。

您只需要校准文件/终端/显示器即可像 UTF-8 一样呈现文本输出(确实如此(。


另外,请记住,std::string只是一个字节容器,本质上并不指定或暗示任何特定的编码。所以你的问题是"如何在 Windows 中将 UTF-16(包含日语字符(转换为 UTF-8",或者事实证明,"如何配置我的终端以显示 UTF-8?

如果此字符串的显示是 Visual Studio 局部窗口(您建议的注释">我在调试时在本地窗口中观察到"ret"字符串的值就是这种情况(,那么您就不走运了,因为 VS 不知道您的字符串是什么编码(也不会尝试找出(。

但是,对于 Visual Studio 的其他方面(如控制台输出窗口(,有多种方法可以解决此问题(示例(。

编辑:首先要做一些事情。Windows具有ANSI代码页的概念。它是 Windows 假定的非 Unicode 字符串的默认代码页。每个使用非 Unicode 版本的 Windows API 且未显式指定代码页的程序都使用 ANSI 代码页

ANSI 代码页由控制面板中的"系统默认区域设置"设置驱动。自 2020 年 5 月 10 日起,它位于"区域/管理/更改系统区域设置"下。更改该设置需要管理员权限。

默认情况下,系统默认区域设置设置为英语的 Windows 使用代码页 1252 作为 ANSI 代码页。该代码页不包含日语字符。因此,在这种情况下,在Unicode中不使用日语是困难或不可能的。

看起来OP想要或必须使用一段使用多字节字符串(std::string和/或char*(的第三方C++代码。这并不一定意味着它不知道Unicode,但它可能。OP 尝试执行的操作完全取决于第三方库的编码方式。这可能根本不可能。


看起来您的问题是某些第三方代码需要 ANSI 中的文件名,并使用 ANSI 函数打开该文件。在具有系统区域设置默认值的英语系统中,日语无法转换为 ANSI,因为 ANSI 代码页(实际上为 CP1252(不包含日语字符。

我认为你应该做的是,你应该得到一个短文件名,而不是使用GetShortPathNameW,将该文件路径转换为ANSI,并传递该字符串。喜欢这个:

std::string WstringFilenameTostring(std::wstring str)
{
wchar_t ShortPath[MAX_PATH+1];
DWORD dw = GetShortPathNameW(str.c_str(), ShortPath, _countof(ShortPath));
char AnsiPath[MAX_PATH+1];
int n = WideCharToMultiByte(CP_ACP, 0, ShortPath, -1, AnsiPath, _countof(AnsiPath), 0, 0);
return string(AnsiPath);
}

此代码仅适用于文件名。对于任何其他日语字符串,它将返回废话。在我的测试中,它将"日本語.txt"转换为不可读但字母数字:)