C++的项目,字符编码是一个大坑,不同平台之间的编码往往不一样,如果不同编码格式用一套字符读取格式读取就会出现乱码。因此,一般都是转化成UTF-8这种平台通用,且支持性很好的编码格式。

Unicode、UTF-8的概念不做过多解释,这里说一下ANSI,我第一次看到这个名词,我看成了ASCII。被Mentor狠批一顿。

可以看出,ANSI和ASCII还是有关系的。ANSI也叫本地码。
我们要做到能在Unicode、UTF-8、ANSI这三种编码格式中自由转换。如下图所示:

在C++中,要怎么做呢?当然是用标准库的东西啦,C++11对国际化标准做得还是可以的,提供了这些接口,正如图中虚线所示,标准库没有提供UTF-8到ANSI的互相转化接口,但是我们可以自己封转接口,借用这条路(UTF-8 <=> Unicode <=> ANSI)来实现。

因此,接下来就聊聊UTF8 <=> Unicode和Unicode <=> ANSI。

UTF8 <=> Unicode
先看代码:

std::string UnicodeToUTF8(const std::wstring & wstr)
{std::string ret;try {std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;ret = wcv.to_bytes(wstr);} catch (const std::exception & e) {std::cerr << e.what() << std::endl;}return ret;
}std::wstring UTF8ToUnicode(const std::string & str)
{std::wstring ret;try {std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;ret = wcv.from_bytes(str);} catch (const std::exception & e) {std::cerr << e.what() << std::endl;}return ret;
}

UTF-8是多字节字符串(multibyte string),而Unicode是宽字符字符串(wchar_t string)。

而C++11提供了wstring_convert这个类,这个类可以在wchar_t string和multibyte string之间来回转换;

而codecvt_utf8可以提供UTF-8的编码规则。这个类在#include 中。有了wstring_convert提供宽字符字符串到多字节字符串的转化,而这个转换规则由codecvt_uft8提供。这样子就可以实现UTF8和Unicode的互相转换。

从UTF8到Unicode调用成员函数wstring_convert::from_bytes;
从Unicode到UTF8调用成员函数wstring_convert::to_bytes;

Unicode <=> ANSI

std::string UnicodeToANSI(const std::wstring & wstr)
{std::string ret;std::mbstate_t state = {};const wchar_t *src = wstr.data();size_t len = std::wcsrtombs(nullptr, &src, 0, &state);if (static_cast<size_t>(-1) != len) {std::unique_ptr< char [] > buff(new char[len + 1]);len = std::wcsrtombs(buff.get(), &src, len, &state);if (static_cast<size_t>(-1) != len) {ret.assign(buff.get(), len);}}return ret;
}std::wstring ANSIToUnicode(const std::string & str)
{std::wstring ret;std::mbstate_t state = {};const char *src = str.data();size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);if (static_cast<size_t>(-1) != len) {std::unique_ptr< wchar_t [] > buff(new wchar_t[len + 1]);len = std::mbsrtowcs(buff.get(), &src, len, &state);if (static_cast<size_t>(-1) != len) {ret.assign(buff.get(), len);}}return ret;
}

标准库提供了wcsrtombs和mbsrtowcs这两个函数,当然C的标准库也提供了这两个函数。

讲下wcsrtombs,这个函数把宽字符串转成多字节字符串。编码规则受地域的LC_CTYPE影响。因此这个函数可以用于本地码的转化(和本地的编码息息相关)。

因此,有关于本地码的使用,在代码中要加上下列语句:

setlocale(LC_CTYPE, "");

目的是让本地码生效,这条代码的作用就是让C++语言的Locale(地域)和本地的地域相同。在Linux下可以运行locale命令看看:

可以看到,LC_CTYPE = en_US.UTF-8,这表示英文,英国,UTF-8编码,也就是说本地码就是这个。

当然,你也可以在setlocale中指定一些编码规则,把wcsrtombs用于别的编码转化,但是,这里不推荐,因为setlocale是全局的,设置了这个就会影响其他地方的编码。

wcsrtombs的四个参数分别代表什么意思呢?

std::size_t wcsrtombs( char* dst, const wchar_t** src, std::size_t len, std::mbstate_t* ps );

dst,转化后的结果存入dst指向的内存;
src,待转化的字符串的指针的指针;
len,dst指向内存的可用字节数;
ps,转换的状态,一般默认初始化就好了;
return type,转化后结果的长度,不包含\0。
注意:如果dst == nullptr,这个时候wcstombs的返回值表示会有这么多字节的结果产生,因此,我们可以拿到这个返回值去新建一个数组来存储new char[len + 1]。所以,一般调用两次wcstombs。

mbsrtowcs同理。

UTF-8 <=> ANSI
以Unicode为中介装换便是

std::string UTF8ToANSI(const std::string & str)
{return UnicodeToANSI(UTF8ToUnicode(str));
}std::string ANSIToUTF8(const std::string & str)
{return UnicodeToUTF8(ANSIToUnicode(str));
}

总结
C++11的标准库还是挺强大的,虽然这么强大,但是很多特性还不了解,因此还是要多扩宽自己的视野,不然有好东西都不知道用,那就棒槌了。

对了,在Linux下加上setlocale(LC_CTYPE, “”)后程序在命令行中可以正常显示,不加有可能不正常显示,原因是setlocale(LC_CTYPE, “”)也影响了cout,全局的嘛;而在CodeBlocks下不能正常显示,不知道为什么,但是调试的过程中,观察到了正常的结果;Visual Studio中没有做实验,不过应该没问题。

c++ ANSI与utf8互相转换相关推荐

  1. 字符串处理 - ANSI - Unicode - UTF8 转换

    字符串处理 - ANSI - Unicode - UTF8 转换 [C语言]字符串处理 - ANSI - Unicode - UTF8 转换 2008-11-4: 使用MultiByteToWideC ...

  2. android mp3 lrc歌词文件utf-8歌词显示为乱码,百度歌词显示乱码 LRC歌词批量转换 UTF-8编码批量转换为GB或ANSI 文本编码批量转换...

    百度歌词显示乱码LRC歌词批量转换UTF-8编码批量转换为GB或ANSI 文本编码批量转换 当从百度下载很多歌词的时候,发现在一些MP3上播放总是显示乱码,这时以为是MP3的问题或者是百度歌词的问题, ...

  3. 关于ANSI和UTF-8,windows和unix的行结束符

    2019独角兽企业重金招聘Python工程师标准>>> 今天帮同事调个东西,发现他的一个配置文件(文本文件)不能正确的被我的程序解析,对比了一个可用的配置文件之后,也没发现什么特别大 ...

  4. 多字节 unicode和utf-8的转换

    本来在网上能找到很多这方面的代码,但很多都是转帖,且很多细节让人理解起来很别扭,估计有的 转帖的也是不知所云. 虽说就两个Windows API的调用,但只有自己去写代码测试研究,才真正领会了这些细节 ...

  5. 统计“3_人民日报语料”文本中的字符数和词数,把文件分别保存为 ansi, UTF8,UTF16,unicode 格式

    统计"3_人民日报语料"文本中的字符数和词数,把文件分别保存为 ansi, UTF8,UTF16,unicode 格式; 首先,统计文件的字符数,有两种方法.第一种是将文件复制到w ...

  6. asp不同编码下 UTF-8 GB2312转换收集

    用于gb2312下接收新浪api 的json数据utf-8转gb2312 ' UTF-8字符转换成GB2312 Function UTF2GB(UTFStr) For Dig=1 to len(UTF ...

  7. 介绍一下unicode,ansi,utf-8,unicode big endian编码

    介绍一下unicode,ansi,utf-8,unicode big endian编码 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们看到8个开关状 ...

  8. UNICODE与UTF-8的转换详解

    UNICODE与UTF-8的转换详解 1 编码 在计算机中,各种信息都是以二进制编码的形式存在的,也就是说,不管是文字.图形.声音.动画,还是电影等各种信息,在计算机中都是以0和1组成的二进制代码表示 ...

  9. UNICODE与 UTF-8的转换详解

    1 编码 在计算机中,各种信息都是以二进制编码的形式存在的,也就是说,不管是文字.图形.声音.动画,还是电影等各种信息,在计算机中都是以0和1组成的二进制代码表示的.为了区分这些信息,人们就为计算机设 ...

最新文章

  1. 图表+笔记-python语言-第5章:数字/5.11 位操作
  2. 【Linux】目录文件权限的查看和修改【转】
  3. 简单帐表插件开发示例分享
  4. Dijkstra-解决最短路径问题
  5. 【LeetCode笔记】338. 比特位计数(Java、位运算、动态规划)
  6. 研发的未来在哪里?Serverless 云开发来了!
  7. 股灾情形下搞了个满堂红,我也是醉了
  8. 世界坐标和本地坐标之间的转换
  9. 网易云计算机系统有限公司,网易云音乐官方电脑版
  10. 红绿3d眼镜与红蓝3d眼镜区别_3D眼镜是指什么原理?
  11. Candence中查看MOS管阈值电压Vth、Vgs、Vds、跨导gm、Id等详细MOS参数的方法
  12. nas架设php网站,使用QNAP NAS虚拟主机功能架设多个网站
  13. GP232RL与FT232RL操作区别
  14. python之开三次方根的计算
  15. Google首席软件工程师Joshua Bloch谈如何设计一款优秀的API
  16. 【making tools】:算英语文章中单词个数,给英语老师使用
  17. 520表白文案来了[联络易]
  18. 字节跳动(今日头条)推荐算法实习生面试
  19. 展示5G和AI的魅力,智博会这个展区为啥人气最旺?
  20. 课程设计(毕业设计)—基于机器学习KNN算法手写数字识别系统—计算机专业课程设计(毕业设计)

热门文章

  1. PAT考试C++总结(二)
  2. 人渣、人员、人手、人才、人物,员工五大类,你怎么搭配?
  3. i5 1155G7和i7 1195G7选哪个好
  4. swig模板 PHP,认识一下swig前端模板引擎
  5. flutter rabbitmq
  6. 调用notifyDataSetChanged不起作用的解决办法
  7. 15亿红包开启后,支付宝DAU和新增提升显著
  8. 【学习Day5】接口和抽象类的区别、作用和使用场景
  9. 操作系统的镜像是什么
  10. js将html页面转为pdf