c++字符编码转换

简述

字符编码一直是软件开发中很麻烦的问题。当前项目开发普遍使用的字符集是utf-8,而windows系统则默认是gbk,linux默认编码则是utf-8,所以想要开发一个在windows正常运行的软件,就需要考虑字符集的问题。

c++11新增了很多本地化的功能,包括字符编码转换等,主要使用wstring_convert和codecvt相结合进行转换,下面介绍具体的方法供大家学习(复制粘贴 )。

windows:gbk编码,std::wstring = std::u16string,wchar_t = char16_t (utf-16编码)

linux:utf-8编码,std::wstring = std::u32string,wchar_t = char32_t (utf-32编码)

编码转换

  • 依赖的头文件:

    #include <codecvt>
    #include <locale>
  • 转换方法:

    coding.h

    #ifndef TE_TEST_CODING_H
    #define TE_TEST_CODING_H #include <string> namespace coding { #ifdef _WIN32
    //GBK locale name in windows
    inline constexpr const char * GBK_LOCALE_NAME = ".936";
    #else
    inline constexpr const char * GBK_LOCALE_NAME = "zh_CN.GBK";
    #endif /**
    * utf-8 --> wchar
    * @param _utf8 要求std::string的编码是utf-8
    * @return 宽字符串
    */
    std::wstring utf8_to_wstr(const std::string& _utf8); /**
    * wchar --> utf-8
    * @param _wstr 宽字符串
    * @return 转化为utf-8 编码的字符串
    */
    std::string wstr_to_utf8(const std::wstring& _wstr); /**
    * utf-8 --> gbk
    * @param _utf8 utf-8
    * @return gbk
    */
    std::string utf8_to_gbk(const std::string& _utf8); /**
    * gbk --> utf-8
    * @param _gbk gbk
    * @return utf-8
    */
    std::string gbk_to_utf8(const std::string& _gbk); /**
    * gbk --> std::wstring
    * @param _gbk gbk
    * @return 宽字符串
    */
    std::wstring gbk_to_wstr(const std::string& _gbk); /**
    * std::wstring --> gbk
    * @param _wstr 宽字符串
    * @return gbk
    */
    std::string wstr_to_gbk(const std::wstring& _wstr);
    } #endif //TE_TEST_CODING_H

    coding.cpp

    #include "coding.h"
    
    #include <codecvt>
    #include <locale> // 包装 wstring/wbuffer_convert 所用的绑定本地环境平面的工具
    template<class Facet>
    struct deletable_facet : Facet
    {
    template<class ...Args>
    explicit deletable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
    ~deletable_facet() override = default;
    }; std::wstring coding::utf8_to_wstr(const std::string &_utf8) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    return converter.from_bytes(_utf8);
    } std::string coding::wstr_to_utf8(const std::wstring &_wstr) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
    return convert.to_bytes(_wstr);
    } std::string coding::utf8_to_gbk(const std::string &_utf8) {
    std::wstring tmp_wstr = utf8_to_wstr(_utf8);
    return wstr_to_gbk(tmp_wstr);
    } std::string coding::gbk_to_utf8(const std::string &_gbk) {
    std::wstring tmp_wstr = gbk_to_wstr(_gbk);
    return wstr_to_utf8(tmp_wstr);
    } std::wstring coding::gbk_to_wstr(const std::string &_gbk) {
    using codecvt = deletable_facet<std::codecvt_byname<wchar_t, char, mbstate_t>>;
    std::wstring_convert<codecvt> convert(new codecvt(GBK_LOCALE_NAME));
    return convert.from_bytes(_gbk);
    } std::string coding::wstr_to_gbk(const std::wstring& _wstr) {
    using codecvt = deletable_facet<std::codecvt_byname<wchar_t, char, mbstate_t>>;
    std::wstring_convert<codecvt> convert(new codecvt(GBK_LOCALE_NAME));
    return convert.to_bytes(_wstr);
    }

补充说明

结构体deletable_facet的作用是公有化codecvt_byname模板类的析构函数,该类的析构函数默认为 protected。部分编译环境实现允许析构析构方法为保护的对象,但部分(如GUN)要求自定义类,继承 Facet 并有 public 的析构方法,否则会出现以下问题:

In file included from /usr/include/c++/6.2.1/bits/locale_conv.h:41:0,
from /usr/include/c++/6.2.1/locale:43,
from main.cpp:3: /usr/include/c++/6.2.1/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = std::codecvt<wchar_t, char, __mbstate_t>]’:
/usr/include/c++/6.2.1/bits/unique_ptr.h:236:17: required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = std::codecvt<wchar_t, char, __mbstate_t>; _Dp = std::default_delete<std::codecvt<wchar_t, char, __mbstate_t> >]’
/usr/include/c++/6.2.1/bits/locale_conv.h:218:7: required from here
/usr/include/c++/6.2.1/bits/unique_ptr.h:76:2: error: ‘virtual std::codecvt<wchar_t, char, __mbstate_t>::~codecvt()’ is protected within this context
delete __ptr;
^~~~~~
In file included from /usr/include/c++/6.2.1/codecvt:41:0,
from main.cpp:1:
/usr/include/c++/6.2.1/bits/codecvt.h:426:7: note: declared protected here
~codecvt();
^

详情可见官方文档说明

本文参考了博客并在其基础上进行补充完善,修复了部分问题。

c++字符编码转换的更多相关文章

  1. iconv字符编码转换

    转自 http://blog.csdn.net/langresser_king/article/details/7459367 iconv(http://www.gnu.org/software/li ...

  2. Char Tools,方便的字符编码转换小工具

    工作关系,常有字符编码转换方面的需要,写了这个小工具 Char Tools是一款方便的字符编码转换小工具,基于.Net Framework 2.0 Winform开发 主要功能 URL编码:URLEn ...

  3. php 字符编码转换函数 iconv mb_convert_encoding比较

    在使用PHP处理字符串时,我们经常会碰到字符编码转换的问题,你碰到过iconv转换失败吗? 发现问题时,网上搜了搜,才发现iconv原来有bug ,碰到一些生僻字就会无法转换,当然了配置第二个参数时, ...

  4. 编码问题 php字符编码转换类

    各种平台和软件打开显示的编码问题,需要使用不同的编码,根据我们不同的需求. php 字符编码转换类,支持ANSI.Unicode.Unicode big endian.UTF-8.UTF-8+Bom ...

  5. Python—字符编码转换、函数基本操作

    字符编码转换 函数 #声明文件编码,格式如下: #-*- coding:utf-8 -*- 注意此处只是声明了文件编码格式,python的默认编码还是unicode 字符编码转换: import sy ...

  6. php字符编码转换之gb2312转为utf8(转)

    在php中字符编码转换我们一般会用到iconv与mb_convert_encoding进行操作,但是mb_convert_encoding在转换性能上比iconv要差很多哦.string iconv ...

  7. day4学python 字符编码转换+元组概念

    字符编码转换+元组概念 字符编码转换 #coding:gbk //此处必声明 文件编码(看右下角编码格式) #用来得到python默认编码 import sys print(sys.getdefaul ...

  8. erlang中字符编码转换(转)

    转自:http://www.thinksaas.cn/group/topic/244329/ 功能说明: erlang中对各种语言的编码支持不足,此代码是使用erlang驱动了著名的iconv编码库来 ...

  9. Qt代码区字符编码转换

    在做通讯练习的时候,发现发送给小助手字符乱码,图片如下 本人Qt Creator是UTF-8,需要改成gbk,代码如下 #include<QTextCodec> // 提供字符编码转换 Q ...

  10. C++ 字符编码转换类

    记录一下C++ 编码转换的函数: #pragma once #include "afx.h" #define DEFAULT_CODE 0 #define CHINESE_SIMP ...

随机推荐

  1. Nginx负载配置

    目录 Nginx 负载均衡笔记 1. 概述 1.1 Nginx 简介 1.2 负载均衡概述 2. 四层负载均衡(传输层) 2.1 工作原理 2.2 特点 2.3 优缺点 优点 缺点 2.4 示例场景 ...

  2. ARP协议介绍与投毒攻击

    目录 ARP是什么? ARP协议工作原理 ARP攻击原理 攻击软件 防范 Reference ARP是什么? ARP是通过网络地址(IP)来定位机器MAC地址的协议,它通过解析网络层地址(IP)来找寻 ...

  3. 3.1 Y86-64指令集体系结构

    程序员可见的状态 这里的程序员即可以是用汇编代码写程序的人,也可以是产生机器级代码的编译器.程序员可见的状态如下,有15个程序寄存器(%rax,%rbx等),三个一位的条件(ZF,OF,SF) ,程序 ...

  4. iOS开发基础100 - MDM证书申请流程

    申请成为MDM Vendor 首先需要拥有一个 iOS Developer Enterprise Program 帐号; 申请成为MDM Vendor,iOS企业开发帐号默认不支持MDM功能,需要向苹 ...

  5. SQL Server 锁(LOCK)大全

    一.锁(LOCK)知识及应用 1.1 锁的基础知识 在任何多用户的数据库中,必须有一套用于数据修改的一致的规则.对于真正的事务处理型数据库,当两个不同的进程试图同时修改同一份数据时,数据库管理系统(D ...

  6. Python 阿里云OSS文件上传下载与文件删除及检索示例

    阿里云OSS文件上传下载与文件删除及检索示例 实践环境 运行环境: Python 3.5.4 CentOS Linux release 7.4.1708 (Core)/Win10 需要安装以下类库: ...

  7. win10远程桌面连接报错:出现身份验证错误,要求的函数不受支持(CredSSP)

    问题 解决办法 找到路径:计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System 在Syste ...

  8. mybatis关于大于小于:元素内容必须由格式正确的字符数据或标记组成。

    首先是原因: mybatis中< >这两个符号会被识别为标签的开始和结束,用了就会报解析的错误 会报错类似下面这些 1.元素内容必须由格式正确的字符数据或标记组成. 2.Error cre ...

  9. mybatisplus轻松完成一次模糊+分页查询

    之前一直用mybatis+pageinfo完成模糊+分页查询,还需要手写sql语句,之前一直没做尝试,今天试了试mybatisplus一个人完成模糊+分页,挺简单的 有一个小插曲是,我的前端接受的da ...

  10. 初看vue3源码

    因为工作的原因又回到了vue的领域,需要加深对vue和vue生态的了解 也许平时比较多人手机看别人解析怎么看vue源码的,自己动手看vue源码的还是比较少,这次我想自己动手看看 首先 吧代码获取到本地 ...