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
//linux
	re.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  转成unicode
	len = 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);
#else
	re.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
	return 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 转 utf8
	len = 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
//linux
	re.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  转成unicode
	len = 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);
#else
	re.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
	return 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 // !_WIN32


string 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  转成unicode
	len = 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);
#else
	re.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
	return 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  转成unicode
	len = 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);
#else
	re.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
	return 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/298728.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android 15即将到来,或将推出5大新功能特性

Android15 OneUI电池优化 三星最近完成了对其所有设备的稳定版 One UI 6.0 更新的推出&#xff0c;引起了用户的极大兴奋。据新出现的互联网统计数据显示&#xff0c;即将发布的基于 Android 15 的 One UI 7 将通过优化电池和功耗来重新定义用户体验&#xff0c;这是一项具有突…

[AutoSar]基础部分 RTE 04 数据类型的定义及使用

目录 关键词平台说明一、数据类型分类二、Adt三、Idt四、Base 数据类型五、units六、compu methods七、data constraint 关键词 嵌入式、C语言、autosar、Rte 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商TI编程语言C&#xff0c;C编译器HighTec (GCC) 一、数据…

FineBI实战(2):案例架构说明及数据准备

1 系统架构 基于MySQL搭建数据仓库基于Kettle进行数据处理帆软FineBI基于MySQL搭建的数据仓库进行数据分析 2 数据流程图 通过Kettle将MySQL业务系统数据库中&#xff0c;将数据抽取出来&#xff0c;然后装载到MySQL数据仓库中。编写SQL脚本&#xff0c;对MySQL数据仓库中的数…

时序预测 | Matlab实现EEMD-SSA-BiLSTM、EEMD-BiLSTM、SSA-BiLSTM、BiLSTM时序预测对比

时序预测 | Matlab实现EEMD-SSA-BiLSTM、EEMD-BiLSTM、SSA-BiLSTM、BiLSTM时间序列预测对比 目录 时序预测 | Matlab实现EEMD-SSA-BiLSTM、EEMD-BiLSTM、SSA-BiLSTM、BiLSTM时间序列预测对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现EEMD-SSA-BiLSTM、…

Java十种经典排序算法详解与应用

数组的排序 前言 排序概念 排序是将一组数据&#xff0c;依据指定的顺序进行排列的过程。 排序是算法中的一部分&#xff0c;也叫排序算法。算法处理数据&#xff0c;而数据的处理最好是要找到他们的规律&#xff0c;这个规律中有很大一部分就是要进行排序&#xff0c;所以需…

关于 LockWindowUpdate 的最终总结

经过前面两篇文章的”洗礼”&#xff0c;我想&#xff0c;你应该知道了在何种情况下应该使用 LockWindowUpdate。 但接下来我要告诉你的是为什么不能使用它&#xff0c;即使是用于它本身的预期目的。 让我们回到古老的旧时代&#xff0c;那个时候&#xff0c;LockWindowUpdate…

docker、docker-compose 离线安装、shell脚本一键安装、卸载

注&#xff1a;二进制包&#xff0c;与脚本在同级目录 docker 离线安装&#xff1a; 包下载&#xff1a;https://download.docker.com/linux/static/stable/x86_64/ docker_install.sh&#xff1a; #!/bin/bash# 指定 Docker 版本和文件名 DOCKER_VERSION"24.0.7" D…

【InternLM】书生-浦语大模型demo搭建服务接口部署本地映射

目录 前言一、InternLM大模型介绍1-1、大模型简介1-2、InternLM大模型简介1-2-1、InternLM-7B1-2-2、InternLM-20B 二、从0开始搭建InternLM-Chat-7B 智能对话 Demo2-0、环境搭建2-1、创建虚拟环境2-2、导入所需要的包2-3、模型下载2-4、代码克隆2-5、终端运行 三、服务器接口部…

真核微生物基因组质量评估工具EukCC的安装和详细使用方法

介绍&#xff1a; GitHub - EBI-Metagenomics/EukCC: Tool to estimate genome quality of microbial eukaryotes 安装&#xff1a; docker&#xff1a; docker pull microbiomeinformatics/eukcc 推荐conda 环境&#xff1a; conda install -c conda-forge -c bioconda …

Python+Torch+FasterCNN网络目标检测识别

程序示例精选 PythonTorchFasterCNN网络目标检测识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonTorchFasterCNN网络目标检测识别》编写代码&#xff0c;代码整洁&#xff0c;规…

Java-网络爬虫(二)

文章目录 前言一、WebMagic二、使用步骤1. 搭建 Maven 项目2. 引入依赖 三、入门案例四、核心对象&组件1. 核心对象SipderRequestSitePageResultItemsHtml&#xff08;Selectable&#xff09; 2. 四大组件DownloaderPageProcessorSchedulerPipeline 上篇&#xff1a;Java-网…

物联网的感知层、网络层与应用层分享

物联网的概念在很早以前就已经被提出&#xff0c;20世纪末期在美国召开的移动计算和网络国际会议就已经提出了物联网(Internet of Things)这个概念。 最先提出这个概念的是MIT Auto-ID中心的Ashton教授&#xff0c;他在研究RFID技术时&#xff0c;便提出了结合物品编码、互联网…

打造清晰的日志管理策略:如何在 NestJS 中集成 winston 高级日志系统

前言 在Web应用程序的开发过程中&#xff0c;日志管理是不可或缺的一部分。日志可以帮助我们了解应用程序的运行状态&#xff0c;监控系统行为&#xff0c;以及在出现问题时快速定位和解决问题。 对于使用NestJS框架的项目来说&#xff0c;集成一个高效、可扩展的日志系统尤为…

听GPT 讲Rust源代码--compiler(25)

File: rust/compiler/rustc_target/src/spec/mod.rs 在Rust的源代码中&#xff0c;rust/compiler/rustc_target/src/spec/mod.rs文件的作用是定义和实现有关目标平台的规范。 SanitizerSet是一个结构体&#xff0c;用于表示目标平台上存在的sanitizer集合。 TargetWarnings是一…

基于OpenCV的透视变换

基础概念 透视变换(Perspective Transformation)是仿射变换的一种非线性扩展,是将图片投影到一个新的视平面(Viewing Plane)&#xff0c;也称作投影映射(Projective Mapping)。 原理&#xff1a;将二维的图片投影到一个三维视平面上&#xff0c;然后再转换到二维坐标下&#…

Mongodb使用指定索引删除数据

回顾Mongodb删除语法 db.collection.deleteMany(<filter>,{writeConcern: <document>,collation: <document>,hint: <document|string>} ) 删除语法中&#xff0c;除了指定过滤器外&#xff0c;还可以指定写入策略&#xff0c;字符序和使用的索引。 …

《C++语言程序设计(第5版)》(清华大学出版社,郑莉 董渊编著)习题——第2章 C++语言简单程序设计

2-15 编写一个程序&#xff0c;运行时提示输入一个数字&#xff0c;再把这个数字显示出来。 #include <iostream>using namespace std;int main() {// 提示用户输入数字cout << "请输入一个数字: ";// 用于存储用户输入的数字的变量double number;// 从…

Apache Paimon:Streaming Lakehouse is Coming

摘要&#xff1a;本文整理自阿里云智能开源表存储负责人&#xff0c;Founder of Paimon&#xff0c;Flink PMC 成员李劲松&#xff08;花名&#xff1a;之信&#xff09;、同程旅行大数据专家&#xff0c;Apache Hudi & Paimon Contributor 吴祥平、汽车之家大数据计算平台…

Nginx快速入门:worker、master进程的作用和热部署原理(十)

0. 引言 我们通过查询nginx进程&#xff0c;可以发现nginx有两个进程&#xff1a;worker和master。一个程序启动了两个进程&#xff0c;那么这两个进程的作用和区别是什么呢&#xff1f;nginx又是如何利用这两个进程进行工作的呢&#xff1f;nginx不停机热部署又是如何实现的&…

AI绘画Midjourney绘画提示词Prompt大全

一、Midjourney绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭…