当前位置: 首页 > news >正文

C++ UTF-8与GBK字符的转换 —基于Linux 虚拟机 (iconv_open iconv)

 1、UTF-8 和 GBK 的区别

GBK:通常简称 GB  (“国标”汉语拼音首字母),GBK 包含全部中文字符。

UTF-8 :是一种国际化的编码方式,包含了世界上大部分的语种文字(简体中文字、繁体中文字、英文、日文、韩文等语言),也兼容 ASCII 码。UTF-8 则包含全世界所有国家需要用到的字符。

2、UTF-8 和 GBK 的作用:

这两种编码方式的的作用就是,在不同的应用环境中使用特定的编码方式

如果输入字符编码是UTF-8,如果想要将信息转换为汉字呈现在显示器上,就必须进行GBK转码操作,才能在显示屏上看到信息;

如果输入字符编码是GBK,如果想要在系统操作中让嵌入式设备或者编程环境认知它,就需要进行UTF-8转码操作。

3、UTF-8 和 GBK 之间如何转换:

在字符转换的过程中,二者不可以直接进行转换,必须借助于unicode

3.1、UTF-8转GBK

UTF-8——unicode——GBK

3.2、GBK转UTF-8

GBK——unicode——UTF-8

4、UTF-8 转GBK ——C++代码:

4.1、引入Win32

因为linux是32位的,所以首先需要引入Winsows.h库,附带引入iconv.h库

#include<iostream>
#include<string>
#include<string.h>
#ifdef _WIN32
#include<Windows.h>
#else
#include<iconv.h>
#endif // _WIN32
using namespace std;
#ifndef _WIN32

4.2、定义函数

static size_t Convert(char* from_cha, char* to_char, char* in, size_t inlen, char* out, size_t outlen)
{//转换上下文iconv_t cd;cd = iconv_open(to_char, from_cha);if (cd == 0){return -1;}memset(out, 0, outlen);char** pin = &in;char** pout = &out;//返回转换字节数的数量,但是转GBK的时候经常不正确 >=0就是成功size_t re = iconv(cd, pin, &inlen, pout, &outlen);if (cd != 0){iconv_close(cd);}cout << "re=" <<(int) re << endl;return re;
}

4.2.1、iconv库介绍

iconv库——linux的转换字符编码库

        iconv_open()——作用:从字符编码from_char转换为to_char

iconv_open(to_char, from_cha);

        iconv_close():—— 关闭参数所指定的转换描述符 

iconv_close(cd);

 memset库——memset是C库函数

	memset(out, 0, outlen);
  • out -- 指向要填充的内存块。
  • 0 -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
  • outlen -- 要被设置为该值的字符数。

4.3、统计转换后的字节数 使用内置函数

现在格式是UTF8,即CP_UTF8.

int len = MultiByteToWideChar(CP_UTF8,	//转换的格式0,							//默认的转换方式data,						//输入的字节-1,							//输入的字符串大小 -1找\0结束  自己去算0,							//输出(不输出,统计转换后的字节数)0							//输出的空间大小);

4.4、用wtring存储数据,并为其分配大小

wstring udata; //用wstring存储的
udata.resize(len);//分配大小

 4.5、UTF-8转unicode。

将数据写进去,将数据强转为wchar_t类型,适用于windows和linux。

MultiByteToWideChar(CP_UTF8, 0, data, -1, (wchar_t*)udata.data(), len);

 4.6、unicode转GBK。

现在格式转成GBK,即CP_ACP。和UTF-8的参数数量不一样哦

len = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, 0, 0,0, //失败替代默认字符0 //是否使用默认替代  0 false);

 4.7、配置字符大小,转成GBK

utf8.resize(len);
WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, (char*)utf8.data(), len, 0, 0);

4.8、 UTF-8转GBK完整代码

其他都是一样的,只不过加了

#ifdef _WIN32 
......
.....
#else
//linuxre.resize(1024);int inlen = strlen(data);cout << "inlen=" << inlen << endl;Convert((char*)"utf-8", (char*)"gbk", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endif
#endif
string UTF8ToGBK2(const char* data)
{string re = "";//1、UTF8 先要转为unicode  windows utf16
#ifdef _WIN32//1.1 统计转换后的字节数int len = MultiByteToWideChar(CP_UTF8,	//转换的格式0,							//默认的转换方式data,						//输入的字节-1,							//输入的字符串大小 -1找\0结束  自己去算0,							//输出(不输出,统计转换后的字节数)0							//输出的空间大小);if (len <= 0){return re;}wstring udata; //用wstring存储的udata.resize(len);//分配大小//开始写进去MultiByteToWideChar(CP_UTF8, 0, data, -1, (wchar_t*)udata.data(), len);//2 unicode 转 GBK  转成unicodelen = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, 0, 0,0, //失败替代默认字符0 //是否使用默认替代  0 false);if (len <= 0){return re;}re.resize(len);WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);cout << "inlen=" << inlen << endl;Convert((char*)"utf-8", (char*)"gbk", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;
}

5、GBK  转 UTF-8 ——C++代码:

5.1、统计转换后的字节数

//1.1 统计转换后的字节数int len = MultiByteToWideChar(CP_ACP,	//转换的格式0,							//默认的转换方式data,						//输入的字节-1,							//输入的字符串大小 -1找\0结束  自己去算0,							//输出(不输出,统计转换后的字节数)0							//输出的空间大小);

5.2、用wstring存储数据,并为其分配大小 

wstring udata; //用wstring存储的
udata.resize(len);//分配大小

5.3、GBK转unicode 

//开始写进去MultiByteToWideChar(CP_ACP, 0, data, -1, (wchar_t*)udata.data(), len);

 5.4、unicode转UTF-8

//2 unicode 转 utf8len = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, 0, 0,0, //失败替代默认字符0 //是否使用默认替代  0 false);

 5.5、配置字符大小,转成UTF-8

GBK.resize(len);
WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, (char*)GBK.data(), len, 0, 0);

5.6、GBK 转UTF-8 完整代码

其他都是一样的,只不过加了

#ifdef _WIN32
.....
.....
#else
//linuxre.resize(1024);int inlen = strlen(data);Convert((char*)"gbk", (char*)"utf-8", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endif
string GBKToUTF82(const char* data)
{string re = "";
#ifdef _WIN32//1、GBK转unicode//1.1 统计转换后的字节数int len = MultiByteToWideChar(CP_ACP,	//转换的格式0,							//默认的转换方式data,						//输入的字节-1,							//输入的字符串大小 -1找\0结束  自己去算0,							//输出(不输出,统计转换后的字节数)0							//输出的空间大小);if (len <= 0){return re;}wstring udata; //用wstring存储的udata.resize(len);//分配大小//开始写进去MultiByteToWideChar(CP_ACP, 0, data, -1, (wchar_t*)udata.data(), len);//2 unicode 转 utf8  转成unicodelen = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, 0, 0,0, //失败替代默认字符0 //是否使用默认替代  0 false);if (len <= 0){return re;}re.resize(len);WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);Convert((char*)"gbk", (char*)"utf-8", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;
}

6、linux虚拟机测试

6.1、创建文件夹

mkdir test_GBK_UTF-8

6.2、进入文件夹

cd test_GBK_UTF-8

 6.3、创建test_GBK_UTF-8.cpp文件

vim test_GBK_UTF-8.cpp

将刚才代码放进去,按下esc键盘+输入  :wq (有一个:呦),回车

 

6.4、输入

//g++就是运行环境是C++
g++ test_GBK_UTF-8.cpp -o test_GBK_UTF-8

 

6.5、执行

./test_GBK_UTF-8

 6.6、结果

如果不转码,会输出乱码

7、完整代码——基于linux

//GBK转utf-8
#include<iostream>
#include<string>
#include<string.h>
#ifdef _WIN32
#include<Windows.h>
#else
#include<iconv.h>
#endif // _WIN32
using namespace std;
#ifndef _WIN32
static size_t Convert(char* from_cha, char* to_char, char* in, size_t inlen, char* out, size_t outlen)
{//转换上下文iconv_t cd;cd = iconv_open(to_char, from_cha);if (cd == 0){return -1;}memset(out, 0, outlen);char** pin = &in;char** pout = &out;//返回转换字节数的数量,但是转GBK的时候经常不正确 >=0就是成功size_t re = iconv(cd, pin, &inlen, pout, &outlen);if (cd != 0){iconv_close(cd);}cout << "re=" <<(int) re << endl;return re;
}
#endif // !_WIN32string UTF8ToGBK(const char* data)
{string re = "";//1、UTF8 先要转为unicode  windows utf16
#ifdef _WIN32//1.1 统计转换后的字节数int len = MultiByteToWideChar(CP_UTF8,	//转换的格式0,							//默认的转换方式data,						//输入的字节-1,							//输入的字符串大小 -1找\0结束  自己去算0,							//输出(不输出,统计转换后的字节数)0							//输出的空间大小);if (len <= 0){return re;}wstring udata; //用wstring存储的udata.resize(len);//分配大小//开始写进去MultiByteToWideChar(CP_UTF8, 0, data, -1, (wchar_t*)udata.data(), len);//2 unicode 转 GBK  转成unicodelen = WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, 0, 0,0, //失败替代默认字符0 //是否使用默认替代  0 false);if (len <= 0){return re;}re.resize(len);WideCharToMultiByte(CP_ACP, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);cout << "inlen=" << inlen << endl;Convert((char*)"utf-8", (char*)"gbk", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;
}string GBKToUTF8(const char* data)
{string re = "";
#ifdef _WIN32//1、GBK转unicode//1.1 统计转换后的字节数int len = MultiByteToWideChar(CP_ACP,	//转换的格式0,							//默认的转换方式data,						//输入的字节-1,							//输入的字符串大小 -1找\0结束  自己去算0,							//输出(不输出,统计转换后的字节数)0							//输出的空间大小);if (len <= 0){return re;}wstring udata; //用wstring存储的udata.resize(len);//分配大小//开始写进去MultiByteToWideChar(CP_ACP, 0, data, -1, (wchar_t*)udata.data(), len);//2 unicode 转 utf8  转成unicodelen = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, 0, 0,0, //失败替代默认字符0 //是否使用默认替代  0 false);if (len <= 0){return re;}re.resize(len);WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)udata.data(), -1, (char*)re.data(), len, 0, 0);
#elsere.resize(1024);int inlen = strlen(data);Convert((char*)"gbk", (char*)"utf-8", (char*)data, inlen, (char*)re.data(), re.size());int outlen = strlen(re.data());re.resize(outlen);
#endifreturn re;return re;
}int main()
{std::cout << "Hello World! 测试\n";//1、测试utf-8转GBK//cout << UTF8ToGBK(u8"测试UTF-8转GBK") << endl;string in = u8"测试UTF-8转GBK";cout << "输入 utf=" << in << endl;string gbk = UTF8ToGBK2(in.c_str());cout << "gbk=" << gbk << endl;cout << GBKToUTF82(gbk.c_str()) << endl;system("pause");return 0;
}

相关文章:

C++ UTF-8与GBK字符的转换 —基于Linux 虚拟机 (iconv_open iconv)

1、UTF-8 和 GBK 的区别 GBK&#xff1a;通常简称 GB &#xff08;“国标”汉语拼音首字母&#xff09;&#xff0c;GBK 包含全部中文字符。 UTF-8 &#xff1a;是一种国际化的编码方式&#xff0c;包含了世界上大部分的语种文字&#xff08;简体中文字、繁体中文字、英文、…...

云原生十二问

一、什么是云原生&#xff1f; 云原生是在云计算环境中构建、部署和管理现代应用程序的软件方法。现代企业希望构建高度可扩展、灵活且具有弹性的应用程序&#xff0c;可以快速更新以满足客户需求。为此&#xff0c;他们使用现代工具和技术&#xff0c;这些工具和技术本质上支…...

K8Spod组件

一个pod能包含几个容器 一个pause容器(基础容器/父容器/根容器&#xff09; 一个或者多个应用容器(业务容器) 通常一个Pod最好只包含一个应用容器&#xff0c;一个应用容器最好也只运行一个业务进程。 同一个Pod里的容器都是运行在同一个node节点上的&#xff0c;并且共享 net、…...

clickhouse-client INSERT CSV/TSV时跳过错误行

clickhouse-client INSERT CSV/TSV时跳过错误行 在使用clickhouse-client向ck中导入csv文件时&#xff0c;当csv中有个别行数据格式错误时&#xff0c;整个文件就插入失败了&#xff0c;经常会导致丢数据。 经过一番搜索&#xff0c;发现ck提供了两个参数可以跳过错误行&#x…...

直流稳压电源电路

一、稳压电源的技术指标及对稳压电源的要求 稳压电源的技术指标可以分为两大类&#xff1a;一类是特性指标&#xff0c;如输出电压、输出电滤及电压调节范围;另一类是质量指标&#xff0c;反映一个稳压电源的优劣&#xff0c;包括稳定度、等效内阻&#xff08;输出电阻&#x…...

记录爬虫编写步骤

本文讲解 Python 爬虫实战案例&#xff1a;抓取百度贴吧&#xff08;https://tieba.baidu.com/&#xff09;页面&#xff0c;比如 Python爬虫吧、编程吧&#xff0c;只抓取贴吧的前 5 个页面即可。今天一个毕业学生问到一个问题&#xff1a;不清楚编写爬虫的步骤&#xff0c;不…...

SpringBoot配置Swagger2与Swagger3

swagger是什么&#xff1f; 在平时开发中&#xff0c;一个好的API文档可以减少大量的沟通成本&#xff0c;还可以帮助新加入项目的同事快速上手业务。大家都知道平时开发时&#xff0c;接口变化总是很多&#xff0c;有了变化就要去维护&#xff0c;也是一件比较头大的事情。尤…...

C/C++ 枚举

目录 枚举概述 枚举的使用 枚举的大小计算 枚举的优点 C语言中的自定义类型有&#xff1a;结构 位段 枚举 联合 枚举概述 枚举顾名思义就是一一列举&#xff0c;把可能的取值一一列举。 比如我们现实生活中&#xff1a;一周的星期一到星期日是有限的7天&#xff0c…...

P12 音视频复合流——TS流讲解

前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_C…...

三维重建 3D Gaussian Splatting:实时的神经场渲染

目录 概念理解三维高斯喷洒 渲染实例 依赖项: 编译报错: 预训练模型 13G:...

Django Web框架

1、创建PyCharm项目 2、安装框架 pip install django4.2.0 3、查看安装的包列表 4、使用命令创建django项目 django-admin startproject web 5、目录结构 6、运行 cd web python manage.py runserver7、初始化后台登录的用户名密码 执行数据库迁移生成数据表 python man…...

ARCGIS PRO SDK GeometryEngine.Intersection的GeometryDimensionType 枚举

描述几何对象的维度。与 GeometryEngine.Intersection 一起使用。 ​ 成员描述EsriGeometry0Dimension零维&#xff08;点或多点&#xff09;。EsriGeometry1Dimension一维&#xff08;折线&#xff09;。EsriGeometry2Dimension二维&#xff08;多边形或包络&#xff09;。Es…...

Web网页开发-CSS层叠样式表1-笔记

1.CSS的引入方式 (1)内嵌式&#xff1a;把style双标签写在head标签里面&#xff0c;可以影响同种标签 (2)行内式&#xff1a;把style写在标签内部&#xff0c;只能影响当前标签 (3)外链式&#xff1a;创建css文件&#xff0c;使用link将html文件和css文件连接起来 (4)导入式&am…...

如何预防变种.halo勒索病毒感染您的计算机?

尊敬的读者&#xff1a; 在数字时代&#xff0c;威胁网络安全的.halo勒索病毒日益猖狂。本文将深入介绍.halo病毒的攻击方式&#xff0c;以及针对被加密文件的恢复方法和预防措施。在面对被勒索病毒攻击导致的数据文件加密问题时&#xff0c;技术支持显得尤为重要&#xff0c;…...

短网址的新玩法,短到只剩域名

短网址大家应该都不陌生了&#xff0c;一句话就可以解释清楚&#xff0c;把一串很长的网址缩短到只有几个字符依然可以正常访问&#xff0c;缩短之后会更加简洁美观。 那大家见过的短网址一般长啥样呢&#xff0c;比如t.cn/xxxxx、dwz.cn/xxxxx、c1ns.cn/xxxxx。这些短网址都有…...

FA2016AA (MHz范围晶体单元超小型低轮廓贴片) 汽车

随着科技的不断发展&#xff0c;智能汽车逐渐成为人们出行的首选。而其中&#xff0c;频率范围在19.2 MHz ~ 54 MHz的晶体单元超小型低轮廓贴片&#xff08;FA2016AA&#xff09;为汽车打造更智能、更舒适、更安全的出行体验。FA2016AA贴片的外形尺寸为2.0 1.6 0.5 mm&#x…...

【设计模式之美】面向对象分析方法论与实现(一):需求分析方法论

文章目录 一. 需求举例二. 对案例进行需求分析1. 第一轮基础分析2. 第二轮分析优化3. 第三轮分析优化4. 第四轮分析优化5. 最终确定需求 三. 小结 本文主要描述&#xff1a; 面向对象的需求分析方法论 一. 需求举例 假设&#xff0c;你正在参与开发一个微服务。微服务通过 HTT…...

MySQL视图索引执行计划相关十五道面试题分享

目录 一. 视图 1.1 含义 1.2 操作 创建视图 修改视图 删除视图 查看视图 二. 索引 2.1 什么是索引 2.2 为什么要使用索引 2.3 优点 2.4 缺点 2.5 何时不适用索引 2.6 索引何时失效 三. 执行计划 3.1 什么是执行计划 3.2 执行计划的作用 四. 面试题 表结构 …...

vue绑定背景颜色或背景图片 和 nuxtjs动态设置background-image:

v-bind绑定样式表&#xff1a; ---------------------------------------------------------------------------------------------------- HTML写法: <div class"myItem" style"text-align:center; background-image:url(); background-size:auto 100% ;ba…...

案例099:基于微信小程序的外卖小程序的研究与开发

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…...

线程与进程的区别与联系:操作系统入门详解(含 Python 示例)

、先搞懂&#xff1a;进程与线程到底是什么&#xff1f;&#xff08;通俗类比官方定义&#xff09; 1.1 生活化类比&#xff1a;快速建立认知 如果把计算机的操作系统比作一个大型工厂&#xff1a; 进程&#xff1a;就是工厂里的一个个独立车间。每个车间有自己专属的生产资…...

Granite TimeSeries FlowState R1 多步预测效果展示:长期趋势与不确定性量化

Granite TimeSeries FlowState R1 多步预测效果展示&#xff1a;长期趋势与不确定性量化 时间序列预测&#xff0c;听起来挺专业的&#xff0c;但说白了&#xff0c;就是根据过去的数据&#xff0c;猜猜未来会发生什么。比如&#xff0c;老板问你&#xff1a;“下个月咱们产品…...

两端间隔数总个数

两端间隔数总个数 结尾序号 - 开头序号 1需要将索引还原成长度&#xff0c;索引1就好了...

告别手动启动:教你写一个ROS2 Launch文件,一键运行robot_state_publisher和rviz2显示URDF

ROS2高效开发指南&#xff1a;用Launch文件一键启动机器人可视化系统 每次调试URDF模型都要重复输入一堆命令&#xff1f;手动启动robot_state_publisher、joint_state_publisher和rviz2节点不仅浪费时间&#xff0c;还容易遗漏参数。本文将带你深度掌握ROS2 Launch文件的编写…...

微信小程序登录总失败?从‘一次性code’到‘缓存清理’,这份避坑指南帮你全搞定

微信小程序登录全链路排雷手册&#xff1a;从原理到实战的深度解析 登录功能作为微信小程序用户体系的入口&#xff0c;其稳定性直接影响用户体验和业务转化。但在实际开发中&#xff0c;开发者常会遇到各种"诡异"问题——明明按照文档实现了流程&#xff0c;却频繁出…...

OpenClaw+GLM-4.7-Flash开发提效:日志分析+异常告警自动化

OpenClawGLM-4.7-Flash开发提效&#xff1a;日志分析异常告警自动化 1. 为什么需要自动化日志监控 作为开发者&#xff0c;我每天要面对服务器、应用和中间件产生的海量日志。曾经为了排查一个线上问题&#xff0c;我需要手动grep几十MB的日志文件&#xff0c;眼睛盯着屏幕找异…...

告别窗口拖拽:用Loop实现Mac高效分屏的5个核心技巧

告别窗口拖拽&#xff1a;用Loop实现Mac高效分屏的5个核心技巧 【免费下载链接】Loop MacOS窗口管理 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 每天在Mac上工作时&#xff0c;你是否经常被这些问题困扰&#xff1a;窗口太多找不到想要的那个&#xff1f;…...

【PVE实战】低成本2.5G网卡升级与iperf3性能验证全记录

1. 为什么需要升级到2.5G网络环境 最近几年&#xff0c;随着NAS、视频剪辑、虚拟机等应用场景的普及&#xff0c;传统的千兆网络&#xff08;1Gbps&#xff09;越来越显得力不从心。我自己就经常遇到这样的情况&#xff1a;在局域网内传输大文件时&#xff0c;千兆网络的极限速…...

Java面试高频:阿里真实面试题——Redis分布式锁实现(3分钟速通,不会直接挂)

一、真实面试场景&#xff08;代入感拉满&#xff09; 上周&#xff0c;一个候选人来面试阿里P6。 技术面已经过了两轮&#xff0c;表现都不错。 最后一轮&#xff0c;面试官只问了一个问题&#xff1a; “你们项目里用过Redis分布式锁吗&#xff1f;怎么实现的&#xff1f;…...

OpenClaw × 88API:不用注册 Anthropic,5 分钟让 AI Agent 接入 Claude 4.6(2026 完整教程)

折腾了两天&#xff0c;最后 5 分钟搞定 上周我想用 OpenClaw 搭一个能自动重构代码的 Agent。选定 Claude 4.6 当大脑——毕竟它在 Tool Use 精准度和长上下文推理上确实是第一梯队。 结果卡在了第一步&#xff1a;Anthropic 官方账号注册要海外手机号&#xff0c;好不容易注…...