当前位置: 首页 > 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 小程序…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...