最近在处理一个字符串转码问题,故记录一下过程
该需求是外部 sdk 的一个 api 需要一个 char* 字符串路径入参,我以往是将宽字符串转为 UTF8 后再传给 sdk
这次这个 api 似乎不接受 UTF8 编码的字符串路径,于是我改用系统编码传参作测试,也就是将 GB2312 编码的字符串路径传给它
结果显示该 api 只接受本地编码的字符串路径,因此我要处理宽字符串转为系统编码的问题
我在 stackoverflow 论坛上搜到一些答案
其中有一个方法要注意避坑,
这是个高赞答案,链接:https://stackoverflow.com/a/12097772/11128312
但是这个只适用于英文字符,因为这种转换相当于把宽字节的第二个字节抹除了,比如,
“帮助” 的 unicode 编码为:2e 5e a9 52
使用上图的方法就给你干掉宽字节的第二个字节,
变成:2e a9
这是一个四不像字符
英文字符就不一样了,比如
“he” 的 unicode 编码为:68 00 65 00
用 std::string 就可以去掉 00,
变成:68 65
故我们要用其他方法来转换,方法很多,我这里列举两个,
C++17 后支持 std::filesystem::path 直接转,示例,
#include <filesystem> const std::wstring wPath = GetPath(); // some function that returns wstring const std::string path = std::filesystem::path(wPath).string();
也可以使用 WcToMb 工具函数
WcToMb 原型:
char* WcToMb(const wchar_t *str) { char *mbstr = NULL; lo_W2C(&mbstr, str); return mbstr; }
lo_W2C 内部也是用的 WideCharToMultiByte 函数转换的
lo_W2C 函数原型
/* ** Convert microsoft unicode to multibyte character string, based on the ** user's Ansi codepage. ** ** Space to hold the returned string is obtained from ** malloc(). */ int lo_W2C(char** pout ,const wchar_t *zWide) { #if (defined(WIN32) || defined(_WIN32) ) char *zname = 0; int codepage = 0; int nByte = 0; if( !zWide || *zWide == '