中文字符编码之GBK,UTF-16和UTF-8

2024-06-23 09:18
文章标签 16 中文 编码 字符 utf gbk

本文主要是介绍中文字符编码之GBK,UTF-16和UTF-8,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

编程中经常会遇到这三种字符编码形式的相互转换问题,以至于许多第三方的库不明原因的调用失败,其实很多都是由于第三方库支持的是utf-8而不是windows默认支持的utf-16导致的。

下面介绍一下windows系统下常见的这三种字符编码方式。

GB2312

是我们国家自己国标的汉字编码字符集,该字符集以一个16位的2进制数据单元表示一个汉字,所以能够将两个char型数据单元保存一个汉字。

微软的Windows操作系统汉字的编码字符集支持GB2312。这就是为什么我们用:

constchar* pChar = “中文”;

printf(pChar);

能够正确显示中文的原因。

但是,假如我们现在要将程序转换为一种除了中文和标准ASCII字符之外的文字时(比如说韩文),由于韩文不能被GB2312解析,所以就会产生乱码。

这就是为什么微软推荐采用Unicode的原因。因为Unicode包含了所有人类已知的文字字符集,理论上可以解析所有文字。

 

Unicode

Unicode字符集实际上是国际标准 ISO 10646 的一个子集。Unicode字符集是由Unicode协会公布的

 

ISO 10646定义了 通用字符集 (Universal Character Set, UCS). UCS 是所有其他字符集标准的一个超集。ISO10646 定义了一个 31 位的字符集. 然而, 在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位(0x0000 0xFFFD). 这个 UCS 16位子集称为基本多语言面 (Basic Multilingual Plane, BMP). 将被编码在 16 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们.

 

 UTF-16

UCS Unicode 只是分配整数给字符的编码表.现在存在好几种将一串字符表示为一串字节的方法. 最显而易见的两种方法是将Unicode 文本存储为 2 4 个字节序列的串. 这两种方法的正式名称分别为 UCS-2 UCS-4. WindowsUnicode表示方式极为UCS-2,即用两个字节表示一个Unicode字符。

除非另外指定, 否则大多数的字节都是Bigendian convention. 将一个 ASCII Latin-1 的文件转换成 UCS-2 只需简单地在每个ASCII 字节前插入 0x00. 如果要转换成UCS-4, 则必须在每个 ASCII 字节前插入三个0x00.

Windows内部使用UCS-2标准,并用UTF-16实现。在基本多语言平面内定义的符号((Basic MultilingualPlane, BMP),或称第零平面(Plane 0)),使用2个字节表示。

所以,Windows中使用的wchar_t的单位为2个字节,一个ASCII字符也要用两个字节表示。

Java采用的也是UTF-16

 

UTF-8

Unix 下使用 UCS-2 (UCS-4) 会导致非常严重的问题. 用这些编码的字符串会包含一些特殊的字符, 比如'\0' '/', 它们在文件名和其他 C 库函数参数里都有特别的含义.另外,大多数使用ASCII 文件的 UNIX 下的工具, 如果不进行重大修改是无法读取 16 位的字符的. 基于这些原因, 在文件名, 文本文件, 环境变量等地方,UCS-2 不适合作为Unicode 的外部编码.

ISO10646-1 Annex R RFC 2279 里定义的UTF-8 编码没有这些问题. 它是在Unix 风格的操作系统下使用 Unicode 的明显的方法.

 

UTF-8有一下特性:

  • UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的.
  • 所有 >U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分.
  • 表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响.
  • 可以编入所有可能的 231个 UCS 代码
  • UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长.
  • Bigendian UCS-4 字节串的排列顺序是预定的.
  • 字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到.

注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.

UTF-8web协议和Unix族的操作系统中广泛使用。ASCII不作变换, 其他字符做变长编码, 每个字符1-3byte.

 搞清了这三种编码方式,下面再谈一下如何相互转化的问题。

//wchar_t转成UTF-8     
inline string ConvertWChar2UTF8( const wchar_t* a_szSrc )     
{         const int nszBuffer = WideCharToMultiByte( CP_UTF8, 0, a_szSrc, -1, NULL, 0, NULL, NULL );     char* Buffer = new char[nszBuffer];  WideCharToMultiByte( CP_UTF8, 0, a_szSrc, -1, Buffer, nszBuffer, NULL, NULL );     string strReturn = Buffer;  delete[] Buffer;  return strReturn;  
} ;


这篇关于中文字符编码之GBK,UTF-16和UTF-8的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086743

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

form表单提交编码的问题

浏览器在form提交后,会生成一个HTTP的头部信息"content-type",标准规定其形式为Content-type: application/x-www-form-urlencoded; charset=UTF-8        那么我们如果需要修改编码,不使用默认的,那么可以如下这样操作修改编码,来满足需求: hmtl代码:   <meta http-equiv="Conte

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

如何将一个文件里不包含某个字符的行输出到另一个文件?

第一种: grep -v 'string' filename > newfilenamegrep -v 'string' filename >> newfilename 第二种: sed -n '/string/!'p filename > newfilenamesed -n '/string/!'p filename >> newfilename

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(