static std::wstring format_string(CONST WCHAR* pszText, ...)
{
std::wstring result;
va_list args;
va_start(args, pszText);
int len = _vscwprintf(pszText, args);
if (len < 0)
{
wprintf_s(L"_vscwprintf failed, len=%i, error=%i\n", len, errno);
return L"";
}
result.resize((size_t)len);
vswprintf_s(const_cast<WCHAR*>(result.data()), result.size() + sizeof(WCHAR),
pszText, args);
va_end(args);
return result;
}
int wmain(int argc, wchar_t* argv[])
{
wprintf_s(L"%S\n", setlocale(LC_ALL, ".UTF8"));
std::wstring msg = format_string(L"msg: %hs", u8"abc 你好");
wprintf_s(L"msg: %s\n", msg.c_str());
return 0;
}
输出:
Chinese (Simplified)_China.utf8
_vsctprintf failed, len=-1, error=0
msg:
操作系统:Windows 10 x64
编译器:vs2019, mingw-w64-v8.1.0
项目字符集:UNICODE
项目文件:test_utf8.zip - 蓝奏云
1
missdeer 2021-05-07 09:30:16 +08:00
用 char*试试
|
2
wtfdsy 2021-05-07 09:56:22 +08:00
格式的%hs 换成%s
|
3
lonewolfakela 2021-05-07 10:21:24 +08:00
盲猜是 windows 的_vscwprintf 系列函数有 bug,不能正常处理 utf8,不然没法解释为啥 len=-1 但是 errno 却是 0……
不知道楼主这段代码的需求是怎样的,能不能换别的函数进行处理? |
4
jones2000 2021-05-07 11:12:27 +08:00
%ls 或%s
|
5
ysc3839 2021-05-07 13:02:26 +08:00 via Android
印象中 C 里面 wchar 系列函数有坑,会根据当前 locale 进行一些转换的。
Windows 下控制台要输出 Unicode 系列编码的字符串,建议转成 UTF-16 然后用 WriteConsole 输出。 |
6
jayvien OP @lonewolfakela 经过一天的尝试,同意你的猜测,UTF-8 编码的字符串只有多字节系列的函数才能正确处理。原始需求是实现一个日志库,传多参,可以正常处理宽字节( UTF-16LE )和多字节( UTF-8 )的日志参数,并且写出 UTF-8 编码的文件。目前已经改成通过多字节系列的函数来实现了,_vscprintf 、vsprintf_s 、printf_s 、fprintf_s,写出文件的时候要用二进制模式,需要 UTF-8 BOM 头的话要自己写"\xEF\xBB\xBF"。
|
7
jayvien OP 需要注意的是,虽然 setlocale 设置了 UTF-8 语言环境,_fsopen 仍然不支持 UTF-8 编码的文件路径,因此需要通过 _wfsopen 打开文件。
|
8
jayvien OP 另外,utf8everywhere 里也有提到一些这方面的技巧,http://utf8everywhere.org/zh-cn
|
9
ysc3839 2021-05-07 20:31:47 +08:00 via Android
@jayvien 你要在 Windows 下使用 UTF-8 文件路径的话,只能把当前进程的 active code page 设置成 UTF-8 来实现,这个操作印象中从 Win10 某个版本开始才支持。否则你必须转换成 UTF-16 。
Windows 中的 Unicode 使用的是 UTF-16 编码。但是为了兼容性,有一些系统 API 有非 Unicode 的版本,这些非 Unicode 的版本内部一般是使用 active code page 转换成 UTF-16 。 |
10
nvioue 2021-05-08 00:16:21 +08:00
....
兄弟你是完全不熟悉 Windows 编程吧... 我给你们简单科普一下 windows 凡是跟字符串相关的 api 大部分都有 A 和 W 两个版本 你用的这个 xxxprint 系列函数我个人认为不算是 windows api. 是 VC 运行库函数, 一样的会映射多字节 multibyte 和 unicode 两个版本. 如果你的目的是混合输出 char 和 wchar 的话... 其实这非常奇怪的需求了. 我建议你统一一下 混合输出你必须手动 MultiByteToWideChar 和 WideCharToMultiByte. 没有人会帮你转换的. 你要知道光简体中文都有 gb2312, gbk, gb18080.. 至少 3 个编码; 你如果是输出中文需求的话可不要小瞧了这两个函数.. 打日志到文件的话没必要这么麻烦, 我告诉你用上述 api 转换完了之后直接用 WriteFile 写文件完事 |