切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
标签
编码
网络协议
正则表达式
时间规范
MCP
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
规范协议
Unicode字符集和UTF编码使用介绍
[TOC] ## 1. Unicode是什么 Unicode是一种字符编码标准,旨在为每个字符提供一个唯一的数字编码,以便在不同计算机系统和语言之间进行一致的文本转换和表示。它为各种语言字符、符号、表情符号等提供了统一的编码,使得它们可以在不同的计算设备、操作系统和应用程序之间正确地显示和传输,Unicode是一个用十六进制编码的字符集,它是国际标准,后续的uft8,utf16等都是在Unicode的基础上进行编码的。 **理解Unicode:** + Unicode将所有的字符映射为一个唯一的数字。这个数字称为码点(Code Point)。 + 不同的编码方式可以将这些码点转换为字节序列。最常用的编码方式是UTF-8,它将大部分字符编码为1到4个字节的序列。 + Unicode标准包含了各种语言的字母、符号、标点符号等,以及图形符号、表情符号等。 > **Tips:**`U+码点`,码点以U+作为前缀,后面跟着若干位十六进制数字 **使用场景:** + 处理多语言文本:Unicode使得在不同语言之间进行文本处理变得容易,避免了不同编码系统之间的转换问题。 + 处理特殊字符和符号:Unicode包含了各种特殊字符和符号,如货币符号、数学符号等。 + 处理表情符号:Unicode包含了大量的表情符号,使得在文本消息、社交媒体和其他领域中可以方便地使用。 **为什么要使用Unicode:** + 避免不同编码系统之间的转换问题:在处理多语言文本时,不同的编码系统可能会导致转换错误。Unicode可以避免这个问题。 + 统一字符表示:Unicode为每个字符提供了一个唯一的编码,使得在不同计算设备、操作系统和应用程序中可以一致地表示字符。 + 支持多种语言:Unicode包含了各种语言的字符,使得在处理不同语言的文本时可以方便地使用。 **使用Unicode的好处:** + 避免乱码问题:在处理不同语言的文本时,乱码是一个常见的问题。Unicode可以避免这个问题。 + 支持多种语言:Unicode包含了各种语言的字符,使得在处理不同语言的文本时可以方便地使用。 + 统一字符表示:Unicode为每个字符提供了一个唯一的编码,使得在不同计算设备、操作系统和应用程序中可以一致地表示字符。 > **Tips:** > 说了这么多其实unicode就是统一了编码,它是一种国际规范,为每个字符提供了一个数字,这个数字被称作码点,Unicode就是这些码点组成的字符集,这里的字符可以是语言文字字符(如:汉字),表情字符,特殊符号字符等 **使用C#举例说明:**获取unicode的数值,将数值转换成码点 ```csharp string message = "你好, 世界!"; // 使用Unicode字符表示中文 uint[] bt = new uint[message.Length]; for (int i = 0; i < message.Length; i++) { bt[i] = Convert.ToUInt32(message[i]); // 获取每个字符对应的Unicode数值 Console.WriteLine(Convert.ToString(bt[i],2)); // 这里将会用二进制的方式将Unicode打印出来,如果要打印16进制的只需将2改成16即可 } string unMessage = ""; for (int i = 0; i < bt.Length; i++) { char c = Convert.ToChar(bt[i]); // 将码点转成字符 unMessage += c; } Console.WriteLine(unMessage); // 输出中文文本 ``` > 在C#中,可以使用字符串来表示Unicode字符 ## 2. UTF编码 UTF是“Unicode Transformation Format”的缩写,它是一种将Unicode码点转换为字节序列的编码方式。UTF-8、UTF-16和UTF-32都是Unicode的编码格式,它们通过不同的字节序列来表示同一个字符。 与Unicode相对应的是ASCII码,它只支持基本的英文字符集,而Unicode则支持全球范围内的各种字符集。因此,UTF系列编码格式使得我们能够使用统一的编码来表示各种字符,从而方便了国际交流和数据交换。 ### 2.1. UTF-8编码 UTF-8编码方式是采用的二进制,8位存储的编码格式,它的码点编码占用1~4个字节,具体取决于码点数值中有效二进制位的数量,它是一种变长字符编码 #### 2.1.1. Unicode与UTF8范围对照 |Unicode|UTF8| |--|--| |U+0000到U+007F:<br/>ASCII字符集,包含128个字符。|U+0000到U+007F:<br/>ASCII字符集,使用1个字节表示,即从00000000到01111111,即0x00到0x7F。| |U+0080到U+07FF:<br/>包含额外的128个字符,用于支持西欧和其他语言的扩展字符集。|U+0080到U+07FF:<br/>使用2个字节表示,即从110xxxxx 10xxxxxx,占用2个字节。| |U+0800到U+FFFF:<br/>包含额外的65536个字符,用于支持各种语言的扩展字符集。|U+0800到U+FFFF:<br/>使用3个字节表示,即从1110xxxx 10xxxxxx 10xxxxxx,占用3个字节。| |U+10000到U+10FFFF:<br/>包含额外的161280个字符,用于支持古代语言和各种特殊字符。|U+10000到U+10FFFF:<br/>使用4个字节表示,即从11110xxx 10xxxxxx 10xxxxxx 10xxxxxx,占用4个字节。| > <span id="binary">**Tips:**</span> > 使用下面代码将16进制转化为10进制方便对比大小 > |16进制|10进制| |--|--| |U+0000到U+007F|0-127| |U+0080到U+07FF|128-2047| |U+0800到U+FFFF|2048-65535| |U+10000到U+10FFFF|65536-1114111| >**使用C#转换进制:** >```csharp public static void UnicodePointToTen() { Console.WriteLine(Convert.ToInt64("6c49", 16)); // 输出27721 Console.WriteLine(Convert.ToInt16("110110001001001", 2)); // 输出27721 Console.WriteLine(Convert.ToChar(Convert.ToInt16("110110001001001", 2))); // 输出'汉' } ``` #### 2.1.2. UTF-8 的编码规则 + **单字节规则:**对于单字节的字符,字节的第一位设为`0`,后面7位为这个符号的Unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的, 所以UTF-8能兼容ASCII编码 + **多字节规则:**对于`N`字节的字符 `(N>1)`,第一个字节的前`N`位都设为`1`,第`N + 1`位设为`0`,后面字节的前两位一律设为`10` 。剩下的的二进制位,全部为这个符号的Unicode码的二级制位 > 2个字节的格式【`11`<sup>N</sup><mark>0</mark><sup>N+1</sup>xxxxx `10`xxxxxx】,x是对应unicode的二进制码位 #### 2.1.3. 多字节编码规则示例 **下面以`'汉'`这个字符为例,查看UTF8的编码规则:** + 获取`'汉'`字符的16进制,即Unicode码点:获取的码点为`U+6c49` ```csharp public static void UnicodePoint() { char message = '汉'; uint binary = Convert.ToUInt32(message); Console.WriteLine(Convert.ToString(binary, 16)); // 输出'汉'字符的16进制【6c49】 Console.WriteLine(Convert.ToString(binary, 10)); // 输出'汉'字符的10进制【27721】 Console.WriteLine(Convert.ToString(binary, 2)); // 输出'汉'字符的2进制【110110001001001】 } ``` + 将`'汉'`字符的Unicode码点转成10进制对比[上面](#binary)的范围,它在`U+0800到U+FFFF`范围内,再对比UTF8的规则,`'汉'`字符占了3个字符,因此规则是1110xxxx 10xxxxxx 10xxxxxx |Unicode二进制码:|110|110001|001001| |--|--|--|--| |适配规则:|1110xxxx|10xxxxxx|10xxxxxx| |UTF-8编码:|11100110|10110001|10001001| + 从`'汉'`字符字的最后一个二进制位开始,按照从后向前的顺序依次填入格式中的x字符,多出的二进制补为0,上面表格1110xxxx需要4个码位,而Unicode二进制码只剩下3个,因此需要补充一个0在110前面,最后补位结果就是`11100110` >**Tips:** >**使用下面C#代码可以对上面转换的结果进行验证:** >```csharp public static void Check() { // 将二进制字符串转换为字节数组 string binaryString = "111001101011000110001001"; // "汉"的二进制表示 byte[] bytes = new byte[binaryString.Length / 8]; for (int i = 0; i < binaryString.Length / 8; i++) { string substring = binaryString.Substring(i * 8, 8); bytes[i] = Convert.ToByte(substring, 2); } // 将字节数组转换为UTF-8编码的字符串 string str = Encoding.UTF8.GetString(bytes); Console.WriteLine(str); // 输出 "汉" } ``` ### 2.2. UTF-16编码 UTF-16也是一种变长字符编码, UTF-16使用16位(2字节)编码字符,它将平面字符编码成2字节将辅助平面的字符编码成4字节 #### 2.2.1. Unicode与UTF16范围对照 |Unicode|UTF16| |--|--| |U+0000至U+FFFF:<br/>基本多语言平面字符|0x0000至0xFFFF:2个字节<br/>0000000000000000到1111111111111111| |U+10000至U+10FFFF:<br/>辅助平面字符|0x10000至0x10FFFF:4个字节<br/>格式:110110yy yyyyyyyy - 110111xx xxxxxxxx<br/>10011100010000到100001111111111111111| > <span id="binary">**Tips:**</span> > 使用下面代码将16进制转化为10进制方便对比大小 > |16进制|10进制| |--|--| |U+0000至U+FFFF|0-65535| |U+10000至U+10FFFF|65536-1114111| #### 2.2.1. UTF-16编码规则 + 对于基本多语言平面(BMP)中的字符(U+0000至U+FFFF),直接使用一个16位(2个字节)编码单元表示,Unicode也是用16位编码的,因此这个规则无需再编码了。 > **示例:** > ```TEXT Unicode 码点: U+0041 ('A') UTF-16 编码: 0x0041 Unicode 码点: U+6c49 ('汉') UTF-16 编码: 0x6c49 ``` + 对于辅助平面字符(U+10000至U+10FFFF),需要使用一对16位(4个字节)编码单元表示,称为高代理项和低代理项,高代理项由2个字节存储,转成2个8位的二进制,前面固定6位为`110110`,同样低代理项也由2个字节存储,转成二进制前面固定6位为`110111`,高低项各剩余10位二进制位就需要补充,补充的内容是`符号的Unicode码`减去`0x10000`的结果转成二级制码位 > **Tips:**使用16进制的运算方式如下,如果差值不足20位,在高位(左边)补0 > + `110110`16进制是`0XD800`,高代理项 = ((`符号的Unicode码` - `0x10000`) 二进制前10位 ) 转成16进制 + `0XD800` > + `110111`16进制是`0xDC00`,低代理项 = ((`符号的Unicode码` - `0x10000`) 二进制后10位 ) 转成16进制 + `0xDC00` #### 2.2.3. 辅助平面字符编码规则示例 **下面以`'😂'`这个字符为例,查看UTF16的编码规则:** + 获取`'😂'`字符的16进制:0x1f602 ```csharp public static void UnicodePoint() { string message = '😂'; int unicodeCodePoint = char.ConvertToUtf32(emoji, 0); Console.WriteLine(Convert.ToString(unicodeCodePoint, 16)); // 输出😂字符的16进制【0x1f602】 } ``` + 获取补充码位的内容,用`'😂'`的Unicode减去固定的`0x10000`,然后结果转成二进制码位 ```csharp public static void Binary16Minus() { var val = 0x1f602 - 0x10000; Console.WriteLine(Convert.ToString(val, 2)); //差值二进制:1111011000000010 Console.WriteLine(val.ToString("X")); //差值16进制:0xF602 } ``` + 通过上面代码获取到差值二进制码,然后填充到UTF16的编码规则中 |差值`0x1f602 - 0x10000`的二进制:|1111011000000010| |--|--|--|--| |适配规则:|110110yy yyyyyyyy - 110111xx xxxxxxxx| |UTF-16编码:|110110`0000`111101 - 1101111000000010| > **Tips:** > 从`'😂'`字符字的最后一个二进制位开始,按照从后向前的顺序依次填入格式中的x字符,填充完毕x后再用同样的方式填充y,直到全部填充完毕,如果不够补0,上面`0000`是差值的二进制位不够补的0 *** **使用C#代码实现UFT16编码过程** ```csharp public static void Binary16Minus() { var emoji = "😂"; int unicodeCodePoint = char.ConvertToUtf32(emoji, 0); var val = unicodeCodePoint - 0x10000; string er = Convert.ToString(val, 2).PadLeft(20,'0'); // 不足20位用0补全 Console.WriteLine(er); // 输出:00001111011000000010 int high = Convert.ToInt32(er.Substring(0,10), 2) + Convert.ToInt32(0XD800); // 获取高代理项 Console.WriteLine(high.ToString("X2"));// 值转成16进制 D83D Console.WriteLine(Convert.ToString(high, 2)); //1101100000111101 int low = Convert.ToInt32(er.Substring(10, 10), 2) + Convert.ToInt32(0xDC00); // 获取低代理项 Console.WriteLine(low.ToString("X2"));// 值转成16进制 DE02 Console.WriteLine(Convert.ToString(low, 2)); //1101111000000010 Console.WriteLine(Convert.ToString(high, 2) + Convert.ToString(low, 2)); // 获取到"😂"的UTF16编码 } ``` >**Tips:**代码获取的结果和上面表格中填充二进制的结果是一致的都是:1101100000111101 1101111000000010 **使用下面C#代码可以对上面转换的结果进行验证:** ```csharp public static void Check16() { char high = Convert.ToChar(0xD83D); //高代理项 char low = Convert.ToChar(0xDE02); //低代理项 int code = Char.ConvertToUtf32(high, low); //获取Unicode码点 string unicode1 = Convert.ToString(code, 16); //16进制:0x1f602 string unicodeCharacter = char.ConvertFromUtf32(code); //获取Unicode码点对应的字符 Console.WriteLine(unicodeCharacter); // 输出:😂 } ```
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号