最近在处理一个字符串转码问题,故记录一下过程

该需求是外部 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 == '\0' )
return 0; #if defined(_WIN32_WCE)
codepage = CP_ACP ;
#else
codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
#endif
nByte = WideCharToMultiByte(codepage, 0, zWide, -1, 0, 0, 0, 0);
zname = (char*)malloc( nByte + 1 );
if( zname == 0 ) return 0; nByte = WideCharToMultiByte(codepage, 0, zWide, -1, zname, nByte+1, 0, 0);
if( nByte > 0 ) zname[nByte] = '\0'; *pout = zname;
return nByte;
#else const wchar_t* in = zWide;
size_t in_len = wcslen(in);
size_t outlen = bbiconv_counts_wchar_2_gbk(in , in_len);
if( outlen <= 0 )
return -1; char* out_ptr = (char*)malloc( (sizeof(char)) * (outlen+1) );
if( !out_ptr )
return -1; bbiconv_wchar_2_gbk(in , in_len , out_ptr , outlen);
*pout = out_ptr;
return outlen; #endif //#if (defined(WIN32) || defined(_WIN32) ) }

补充:

std::wstring 和 wchar_t 内部中文编码是按照 unicode 编码的
std::string 和 char 内部中文编码是按照系统字符集编码,一般中文是 GB2312 字符集

另附:

std::string std::wstring char w_char 内部中文编码的更多相关文章

  1. std::string stringf(const char* format, ...)

    std::string stringf(const char* format, ...){ va_list arg_list; va_start(arg_list, format); // SUSv2 ...

  2. How to convert a std::string to const char* or char*?

    How to convert a std::string to const char* or char*? 1. If you just want to pass a std::string to a ...

  3. std::string, std::wstring, wchar_t*, Platform::String^ 之间的相互转换

    最近做WinRT的项目,涉及到Platform::String^  和 std::string之间的转换,总结一下: (1)先给出源代码: std::wstring stows(std::string ...

  4. 为什么推荐std::string而不是char*

    例如如下: map<const char*, const char*> map_test; map_test["a"] = "a"; map_tes ...

  5. std::string std::wstring 删除最后元素 得到最后元素

    std::string str = "abcdefg,"; std::cout << "last character:"<<str.ba ...

  6. std::string,std::vector,std::accumulate注意事项

    在用string做字符串拼接时,会发现随着string的增大越来越慢,原因主要是string(和vector)是基于现行内存的数据结构,在海量数据时,经常会申请新的一块内存,把原有的数据拷贝过去然后再 ...

  7. C++ MFC std::string转为 std::wstring

    std::string转为 std::wstring std::wstring UTF8_To_UTF16(const std::string& source) { unsigned long ...

  8. 对std::string和std::wstring区别的解释,807个赞同,有例子

    807down vote string? wstring? std::string is a basic_string templated on a char, and std::wstring on ...

  9. C++ std::unordered_map使用std::string和char *作key对比

    最近在给自己的服务器框架加上统计信息,其中一项就是统计创建的对象数,以及当前还存在的对象数,那么自然以对象名字作key.但写着写着,忽然纠结是用std::string还是const char *作ke ...

  10. QString, Std::string, char *相互转换

    Qt 库中对字符串类型进行了封装,QString 类提供了所有字符串操作方法,给开发带来了便利. 由于第三方库的类型基本上都是标准的类型,即使用std::string或char *来表示字符 (串) ...

随机推荐

  1. [转帖]一个轻量的Linux运维监控脚本

    https://zhuanlan.zhihu.com/p/472040635 写在前面 我的需求 嗯,有几台很老的机器,上面部署的几个很老的应用 我需要每周对机器上的一些内存,磁盘,线程,应用和数据库 ...

  2. 【转帖】JVM 元数据区的内存泄漏之谜

    https://www.infoq.cn/article/Z111FLot92PD1ZP3sbrS 一.问题描述 某天,SRE 部门观察到一个非常重要的应用里面有一台服务器的业务处理时间(Transa ...

  3. 使用 inotifywait的方式监控文件夹发生变化后自动执行脚本的方法

    0. 先安装inotify 最简单的方法为: yum install epel-release 安装扩展包源 yum install inotify-tools 1. 从网上抄了一下脚本 简单记录一下 ...

  4. NOI2023 游记

    不完全按时间顺序写.记录 NOI 的一些琐事. 从 XDFZ 坐大巴 5 个小时来到成七.第一眼看到的是一个放着 NOI 牌子的台阶,还有一个签名墙.好像在我们之前到的人不太多? 用中英双语签名(冷月 ...

  5. ElementUI实现表格(table) 行上下移动的效果

    参考地址 https://blog.csdn.net/sunshine0508/article/details/88390155 看大佬的地址 <div id="app"&g ...

  6. 【JS 逆向百例】网洛者反爬练习平台第三题:AAEncode 加密

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...

  7. webpack重新打包清空dist文件夹的问题

    1.5.20.0以上版本才支持output属性里的clean:true 5.20.0+ 5.20以下版本清除dist文件内容一般使用插件 clean-webpack-plugin, 5.20版本以后o ...

  8. Advanced Installer设置安装最后一步启动软件

    左侧用户界面中选择对话框-ExitDialog 在完成操作项中勾选"安装结束时启动应用程序",在弹出的对话框中选择需要启动的exe文件

  9. Qwik 1.0 发布,全栈式 Web 框架

    Qwik 是一个全栈式 Web 框架,Qwik 基于 React.Angular 和 Vue 等其他 Web 框架的概念,但以 JavaScript 流等更新的方法脱颖而出,允许以高性能向用户交付复杂 ...

  10. 【文件】C语言文件操作及其使用总结篇【初学者保姆级别福利】

    [文件]C语言文件操作及其使用总结篇[初学者保姆级别福利] 一篇博客学好动态内存的管理和使用 这篇博客干货满满,建议收藏再看哦!! 求个赞求个赞求个赞求个赞 谢谢 先赞后看好习惯 打字不容易,这都是很 ...