[原创](Modern C++)现代C++的字符编码迟迟得不到很好地解决(ASCII, ANSI, UNICODE通俗易懂的故事)

常用网名: 猪头三
出生日期: 1981.XX.XX
QQ联系: 643439947
个人网站: 80x86汇编小站
编程生涯: 2001年~至今[共23年]
职业生涯: 21年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测

[序言]
计算机在早期主要用于科学计算和数据处理, 而文字与字符处理不是主要任务. 然而随着计算机的普及, 各个国家开始使用它来处理事务, 这引发了一个根本性问题: 如何有效地描述和显示多种语言的文字以及符号. 最初, 由英语系国家主导的计算机采用ASCII编码, 但是这个字符编码仅限于描述大量的英文和常规符号. 随后, 欧洲国家也开始使用计算机, 这就导致了ASCII无法正确显示欧洲国家的文字和符号. 为了解决这个问题, 出现了ANSI编码, 每个国家都对其进行扩展以包含本国语言的文字和符号, 比如: 中国的中文, 日本的日文... 然而, 使用ANSI编码时存在一个严重的问题: 不同国家扩展本国语言的ANSI编码并不会考虑其他国家的语言兼容性. 这就导致了代码页的概念出现, 即文件内容需要使用对应的代码页才能正确显示. 如果一个ANSI编码格式的文件使用中文代码页保存并发送给日本客户, 那么在日本客户的计算机上打开时就会出现乱码, 因为默认情况下日文计算机使用ANSI编码的日本代码页. 为了解决这个问题, UNICODE字符集标准应运而生. 如果文件内容以UNICODE字符集标准保存, 那么无论发送到哪个国家, 都可以自动化地正确显示对应的语言, 无需做任何代码页的切换, 甚至还有更强大的优势是, 在UNICODE字符集标准下的文件内容可以同时显示多种国家的语言. 这是ANSI编码无法做到的事情, 因为一个ANSI编码格式的文件无法同时处理多个代码页.

[ASCII, ANSI, UNICODE相互转换]
由于UNICODE字符集标准是后来发布的, 早期计算机软件主要使用ASCII或ANSI编码处理内容. 为了适应国际字符标准UNICODE, 需要一套成熟的编码转换代码. 现代C++标准库尚未包含这方面的功能, 但大多数C++开发者会选择使用Boost库或ICU(International Components for UNICODE)库来处理UNICODE字符集标准转换. 如果在Windows平台下开发并不想使用第三方库, 可以选择WIN API中的MultiByteToWideChar()和WideCharToMultiByte()这两个函数进行编码转换. 作为软件开发人员, 优先选择UNICODE字符集标准是显而易见的, 这样可以处理来自不同国家的内容. 

[在使用UNICODE字符集标准之前, 了解什么是UTF-8, UTF-16, UTF-32]
UTF-8是一种可变长度的编码格式, 每个字符可以用1到4个字节表示, 它的最大优点是与ASCII 兼容, 这意味着ASCII编码的文件在UTF-8中无需修改. UTF-8在网络传输和文件存储中非常常用, 因为它节省空间且兼容性好.
UTF-16也是一种可变长度的编码格式, 每个字符用2或4个字节表示, 它对于处理大量亚洲语言字符更有效率.
UTF-32是一种固定长度的编码格式, 每个字符都使用4个字节表示, 虽然其编解码过程简单但存储空间消耗.

[在现代C++中std::wstring宽字符默认使用何种格式的UNICODE字符集标准?]
std::wstring类型默认存储宽字符序列, 其元素类型为wchar_t. 在Windows平台上, wchar_t通常被定义为使用UTF-16编码格式的16位宽(2 字节)数据. 但是, 需要注意的是, 现代C++标准并未规定wchar_t必须为特定大小或使用UNICODE字符集标准格式(如 UTF-8、UTF-16、UTF-32). 因此, 不能假设所有平台上的std::wstring都存储UTF-16编码的数据. 具体采用哪种UNICODE字符集标准格式取决于操作系统和对wchar_t类型的定义. 例如, 在Linux和MacOS系统中, wchar_t可能是32位宽(4字节), 并且使用UTF-32编码格式来表示各种语言的字符.

[如何使用MultiByteToWideChar()和WideCharToMultiByte()进行ASCII, ANSI, UNICODE相互转换]
这段现代C++代码实现了ANSI编码到Unicode字符集标准UTF-8格式的转换过程, 将一个给定的ANSI编码文件转换为UTF-8编码格式的文件, 以便在不同的系统和平台上正确显示其中包含的特殊字符和语言文本 它包括以下主要部分:

fun_AnsiToWide函数: 接收一个ANSI字符串作为参数, 使用Windows API中的MultiByteToWideChar()函数将其转换成宽字符(WideChar)格式, 并返回结果. 
fun_WideToUtf8函数: 接收一个宽字符串作为参数, 使用Windows API中的WideCharToMultiByte()函数将其转换成UTF-8编码的多字节字符串(Multibyte)格式, 并返回结果. 
fun_ConvertAnsiToUtf8函数: 接收两个宽字符串参数分别代表ANSI编码文件和UTF-8编码文件的路径. 它读取ANSI编码文件的内容, 调用fun_AnsiToWide()将其转换成宽字符格式, 再调用fun_WideToUtf8()将宽字符格式转换成UTF-8编码格式, 最后将结果写入到UTF-8编码文件中. 
main()函数:创建两个宽字符串变量分别表示ANSI编码文件和UTF-8编码文件的路径, 调用fun_ConvertAnsiToUtf8()函数进行转换并输出成功信息. 

// ANSI编码->WideChar编码
std::wstring fun_AnsiToWide(const std::string& str_param_ANSI) {int int_Size_Needed = ::MultiByteToWideChar(CP_ACP,0,str_param_ANSI.c_str(),static_cast<int>(str_param_ANSI.size()),NULL,0);// 初始化空字符串wstr_WideChar,长度为int_Size_Needed.// 参数2: 0 表示用零值(空字符)初始化字符串中的每个元素std::wstring wstr_WideChar(int_Size_Needed, 0);::MultiByteToWideChar(CP_ACP,0,str_param_ANSI.c_str(),static_cast<int>(str_param_ANSI.size()),&wstr_WideChar[0],int_Size_Needed);return wstr_WideChar;}// End fun_AnsiToWide()// WideChar编码->UNICODE字符集标准的UTF-8格式
std::string fun_WideToUtf8(const std::wstring& wstr_param_Wide) {int int_Size_Needed = ::WideCharToMultiByte(CP_UTF8,0,wstr_param_Wide.c_str(),static_cast<int>(wstr_param_Wide.size()),NULL,0,NULL,NULL);// 初始化空字符串wstr_UTF8,长度为int_Size_Needed.// 参数2: 0 表示用零值(空字符)初始化字符串中的每个元素std::string wstr_UTF8(int_Size_Needed, 0);::WideCharToMultiByte(CP_UTF8,0,wstr_param_Wide.c_str(),static_cast<int>(wstr_param_Wide.size()),&wstr_UTF8[0],int_Size_Needed,NULL,NULL);return wstr_UTF8;}// End fun_WideToUtf8()// ANSI文件转换UTF-8文件函数
void fun_ConvertAnsiToUtf8(const std::wstring& wstr_param_ANSI_File, const std::wstring& wstr_param_UNICODE_File) {// 创建输入流对象和输出流对象std::ifstream ifs_ANSI_File(wstr_param_ANSI_File, std::ios::binary);std::ofstream ofs_UNICODE_File(wstr_param_UNICODE_File, std::ios::binary);if (!ifs_ANSI_File.is_open() || !ofs_UNICODE_File.is_open()) {std::wcerr << L"打开文件失败!" << std::endl;return;}// 为输入流对象ifs_ANSI_File创建输入流缓冲区迭代器buf_ANSI_File// buf_ANSI_File 是一个从文件流 ifs_ANSI_File 读取字符的迭代器.// buf_End 是一个默认构造的迭代器,表示流的结束位置.std::istreambuf_iterator<char> buf_ANSI_File{ ifs_ANSI_File }, buf_End;// 利用输入流缓冲区迭代器创建一个str_ANSI字符串.std::string str_ANSI{ buf_ANSI_File , buf_End};// ANSI编码->WideChar编码std::wstring wstr_WideChar = fun_AnsiToWide(str_ANSI);// WideChar编码->UNICODE字符集标准的UTF-8格式std::string  str_UTF8      = fun_WideToUtf8(wstr_WideChar);// UNICODE字符集标准的UTF-8格式内容保存到文件ofs_UNICODE_File.write(str_UTF8.c_str(), str_UTF8.size());}// End fun_ConvertAnsiToUtf8()int main()
{std::wstring str_FilePath_ANSI{ L"C:\\Users\\Win_AI\\Desktop\\编码测试\\1-ANSI.txt" } ;  // ANSI 编码的输入文件std::wstring str_FilePath_UTF8{ L"C:\\Users\\Win_AI\\Desktop\\编码测试\\2-UTF-8.txt" };  // UTF-8 编码的输出文件// ANSI文件转换UTF-8文件函数fun_ConvertAnsiToUtf8(str_FilePath_ANSI, str_FilePath_UTF8);std::wcout << L"转换完成!" << std::endl;return 0;}

[结尾]
总之, 随着计算机的普及和多语言处理需求的增加, ASCII编码无法满足需求, 出现了ANSI编码、UNICODE字符集标准、UTF-8、UTF-16和UTF-32等多种字符编码格式. 不同的编码格式具有不同的特点和适用场景, 但强烈建议全部使用UNICODE字符集标准.

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker镜像仓库常用命令

docker镜像仓库常用命令 docker logindocker logoutdocker pulldocker pushdocker searchdocker imagesdocker image inspectdocker tagdocker rmidocker image prunedocker savedocker loaddocker history docker login 语法: docker login [options] [server] 功能&#xff…

软件开发项目管理:实现目标的实用指南

由于软件项目多数是复杂且难以预测的&#xff0c;对软件开发生命周期的深入了解、合适的框架以及强大的工作管理平台是必不可少的。项目管理系统在软件开发中通常以监督为首要任务&#xff0c;但优秀的项目计划、管理框架和软件工具可以使整个团队受益。 软件开发项目管理的主要…

外包干了2年,快要废了。。。

先说一下自己的情况&#xff0c;普通本科&#xff0c;在外包干了2年多的功能测试&#xff0c;这几年因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不能够在这样蹉跎下去了&#xff0c;长时间呆在一个舒适的环境真的会让一…

【青牛科技】GC8549替代LV8549/ONSEMI在摇头机、舞台灯、打印机和白色家电等产品上的应用分析

引言 在现代电子产品中&#xff0c;控制芯片的性能直接影响到设备的功能和用户体验。摇头机、舞台灯、打印机和白色家电等领域对控制精度、功耗和成本等方面的要求日益提高。LV8549/ONSEMI等国际品牌的芯片曾是这些产品的主要选择&#xff0c;但随着国内半导体技术的进步&…

Spring挖掘:(AOP篇)

学习AOP时,我们首先来了解一下何为AOP 一. 概念 AOP&#xff08;面向切面编程&#xff0c;Aspect Oriented Programming&#xff09;是一种编程技术&#xff0c;旨在通过预编译方式或运行期动态代理实现程序功能的统一管理和增强。AOP的主要目标是在不改变原有业务逻辑代码的…

Centos Linux 7 搭建邮件服务器(postfix + dovecot)

准备工作 1. 一台公网服务器&#xff08;需要不被服务商限制发件收件的&#xff0c;也就是端口25、110、143、465、587、993、995不被限制&#xff09;&#xff0c;如有防火墙或安全组需要把这些端口开放 2. 一个域名&#xff0c;最好是com cn org的一级域名 3. 域名备案&am…

深入了解Bootstrap框架:从入门到精通

文章目录 前言Bootstrap的核心特性1. 响应式设计2. 丰富的组件库3. 易于使用4. 良好的兼容性 安装与使用安装1. 通过CDN引入2. 下载源码3. 使用npm或yarn 基本使用1. 栅格系统2. 按钮3. 导航条4. 卡片5. 模态框6. 轮播图7. 表单 高级定制1. 修改 Sass 变量2. 按需引入组件 最佳…

ENSP RIP动态路由

RIP&#xff08;距离矢量路由协议&#xff09;以网络中所有链路的距离和矢量为依据计算最佳路径&#xff0c;是第一个动态路由协议。条数作为唯一的度量单位。默认开启水平分割&#xff08;从一个路由接口学到的路由信息&#xff0c;便不在从这个接口发送出去&#xff09;防止路…

华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)

华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目分享——共九套&#xff08;每套四十题&#xff09; 岗位——芯片与器件设计工程师 岗位意向——模拟芯片 真题题目分享&#xff0c;完整题目&#xff0c;无答案&#xff08;共8套&#xff09; 实习岗位…

MySQL45讲 第十一讲 怎么给字符串字段加索引?

文章目录 MySQL45讲 第十一讲 怎么给字符串字段加索引&#xff1f;一、引言二、前缀索引&#xff08;一&#xff09;概念与创建方式&#xff08;二&#xff09;数据结构与存储差异&#xff08;三&#xff09;确定前缀长度的方法 三、前缀索引对覆盖索引的影响四、其他索引创建方…

字节青训-小S的倒排索引

问题描述 小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子&#xff0c;小S决定使用倒排索引。倒排索引的工作原理是&#xff1a;每个单词都会关联一个帖子ID的列表&#xff0c;这些帖子包含该单词&#xff0c;且ID按从小到大的顺序排列。 例…

讲讲分布式与集群的区别?

大家好&#xff0c;我是锋哥。今天分享关于【讲讲分布式与集群的区别&#xff1f;】面试题。希望对大家有帮助&#xff1b; 讲讲分布式与集群的区别&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在现代计算和信息技术领域&#xff0c;分布式系统和集…

大数据新视界 -- 大数据大厂之 Impala 性能优化:解锁大数据分析的速度密码(上)(1/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

大数据新视界 -- 大数据大厂之 Impala 性能优化:数据存储分区的艺术与实践(下)(2/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【实用教程】Blazor 文件管理器中引入分页功能

分页是一项重要功能&#xff0c;可帮助我们有效地加载大量数据。我们的 Syncfusion Blazor 文件管理器允许在分段页面中显示文件和文件夹&#xff0c;从而更轻松地浏览大型目录。在文件管理器组件中处理大量数据时&#xff0c;此功能非常方便。此功能可用于有效地加载大量数据。…

C++上机实验|多态性编程练习

1.实验目的 (1)理解多态性的概念。 (2)掌握如何用虚函数实现动态联编 (3)掌握如何利用虚基类。 2.实验内容 设计一个飞机类 plane,由它派生出歼击机类fighter和轰炸机类 bomber,歼击机类fighter 和轰炸机类bomber 又共同派生出歼轰机(多用途战斗机)。利用虚函数和虚基类描述…

CSS弹性布局:灵活布局的终极指南

在网页设计中&#xff0c;CSS 弹性布局&#xff08;Flexbox&#xff09;是一个不可或缺的工具。它能帮助你轻松地排列和对齐元素&#xff0c;尤其是在响应式设计中表现出色。今天&#xff0c;我们就来深入探讨一下 Flexbox 的各个属性&#xff0c;让你彻底掌握这个强大的布局工…

Java:二维数组

目录 1. 二维数组的基础格式 1.1 二维数组变量的创建 —— 3种形式 1.2 二维数组的初始化 \1 动态初始化 \2 静态初始化 2. 二维数组的大小 和 内存分配 3. 二维数组的不规则初始化 4. 遍历二维数组 4.1 for循环 ​编辑 4.2 for-each循环 5. 二维数组 与 方法 5.1…

SQL,力扣题目1767,寻找没有被执行的任务对【递归】

一、力扣链接 LeetCode_1767 二、题目描述 表&#xff1a;Tasks ------------------------- | Column Name | Type | ------------------------- | task_id | int | | subtasks_count | int | ------------------------- task_id 具有唯一值的列。 ta…

Spring Security-02-Spring Security认证方式-HTTP基本认证、Form表单认证、HTTP摘要认证、前后端分离安全处理方案

Lison <dreamlison163.com>, v1.0.0, 2024.06.01 Spring Security-02-Spring Security认证方式-HTTP基本认证、Form表单认证、HTTP摘要认证、前后端分离安全处理方案 文章目录 Spring Security-02-Spring Security认证方式-HTTP基本认证、Form表单认证、HTTP摘要认证、…