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

该需求是外部 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. [转帖]TPC-C 、TPC-H和TPC-DS区别

    https://zhuanlan.zhihu.com/p/339886289 针对数据库不同的使用场景TPC组织发布了多项测试标准. TPC-C: TPC Benchmark C于1992年7月获得批 ...

  2. Oracle 高低水位线的学习

    Oracle 高低水位线的学习 背景 最近产品的一些脚本会大量的给一些流程表里面插入数据 因为只是一个流程相关没有时序查询的需求 所以数据量挺大, 但是按照石时间戳删除非常麻烦. 自己执行过多次del ...

  3. [转帖]记一次探索内存cache优化之旅

    https://developer.aliyun.com/article/972803 背景 项目上线以来,曾出现上传镜像.下发镜像时可用内存不足,性能发生抖动的情况.研究发现是容器的 page ca ...

  4. [转帖]TiKV & TiDB相关笔记

    https://www.jianshu.com/p/1141be233bb2 一.TiKV存储 简述 通过单机的 RocksDB,TiKV 可以将数据快速地存储在磁盘上:通过 Raft,将数据复制到多 ...

  5. [转帖]jmeter之使用csv文件传递参数-05篇

    csv文件格式,第一列为手机号,第二列为密码 1.右键添加一个配置元件---csv数据文件设置 2.设置csv数据提取路径 3.引用数据 4.设置线程循环运行两次,然后发送请求 看到结果就执行了两次, ...

  6. [转帖]深入理解mysql-第十章 mysql查询优化-Explain 详解(上)

    目录 一.初识Explain 二.执行计划-table属性 三.执行计划-id属性 四.执行计划-select_type属性 一条查询语句在经过MySQL查询优化器的各种基于成本和规则的优化会后生成一 ...

  7. [转帖]如何升级vCenter(VCSA)补丁?

    https://www.dinghui.org/upgrade-vcsa-patch.html VCSA的升级分为repo源和iso镜像两种方式,由于使用repo源进行升级只支持HTTPS和FTPS协 ...

  8. 使用rpmbuild打包erlang和rabbitmq进行部署服务的方法

    使用rpmbuild打包erlang和rabbitmq进行部署服务的方法 背景说明 1. rabbitmq 是基于 erlang 开发的消息列队, 本身rabbitmq 自己不区分架构. 2. 但是e ...

  9. TS声明promise返回来的数据类型

    promise返回来的数据类型 interface backResult{ code: number, data: { name:string,age:number}[], //数组里面的对象类型,这 ...

  10. [洛谷]P1967-最小生成树-好题推荐

    [NOIP2013 提高组] 货车运输 题目背景 NOIP2013 提高组 D1T3 题目描述 A 国有 \(n\) 座城市,编号从 \(1\) 到 \(n\),城市之间有 \(m\) 条双向道路.每 ...