字符编码(1)——Unicode,utf-8
字符编码
编码是一个将一组Unicode字符转换业个字节序列的过程。而解码是将一个编码字节序列转换为一组Unicode字符的过程。
Unicode字符是什么?
Unicode字符集可以简写为UCS,也就是Unicode charactor set
Unicode编码是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。它通过0到0x10FFFF来映射字符,最多可容纳1114112个字符(16进制的10FFFF的值是1114111,然后加一个0x000000就是1114112个)。可以看一下1114112的二进制表示形式为:1 0001 00000000 00000000
UTF是什么?
UTF是Unicode转换格式的意思,是UCS Transformation Format的缩写。
Utf-8
UTF-8以字节为单位对Unicode进行编码。utf-8特点是对不同范围的字符用不同长度的编码。从Unicode到UTF-8的编码方式如下:
Unicode编码(16进制) ║ UTF-8 字节流(二进制)
000000 - 00007F ║ 0xxxxxxx
000080 - 0007FF ║ 110xxxxx 10xxxxxx
000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
例如:“赵”这个字的Unicode编码(16进制表示方法)是:8d 75
这个编码在.net中可以通过ToString()方法来实现。为了进行后边的说明。这里先给出测试用的转换方法:
{
public static string TransCoding(this int iValue,eTrans eType)
{
return Convert.ToString(iValue, (int)eType);
}
public static string GetCorrectCoding(this string selfChar, Encoding encoding, eTrans eType)
{
int iUnicode = (int)char.Parse(selfChar);
return iUnicode.TransCoding(eType);
}
}
public enum eTrans
{
Binary=2,
Octonary=8,
Decimal=10,
Hexadecimal=16
}
一个枚举,用于枚举数的进制,一个从字串转换到特定的字符编码,并以指定进制表示的方法。
·另外,可以再把系统的计算器调出来,改为科学型。
·准备可以查看进制的编辑器,我用的是ultra。
另外说明一下:char.Parse方法:它将指定字符串的值转换为它的等效 Unicode 字符
百家姓赵钱孙李中的“赵”字,这里是简体赵字。可以查一下它的Unicode编码,并用10进制和16进制表示:
UnicodeEncoding _unicode = new UnicodeEncoding();
string s1 = cc.GetCorrectCoding(_unicode, eTrans. Decimal);
string s2 = cc.GetCorrectCoding(_unicode, eTrans.Hexadecimal);
10进制:36213
16进制:8d75
然后新建立记事本。写一个“赵”字,保存,保存时编码选择unicode。然后用ultra打开。切换到16进制编辑模式。可以看到:FF FE 75 8D
还有一个要说的就是这里的10进制是8D75的10进制表示法,同时也是Unicode编码表中汉字“赵”的编号。
其中8D 75是“赵”字的16进制编码。而多出来的FE FF就是字节序,byte order mark(BOM),用来判断字节流的字节序。在传输字节流前,先传输被作为BOM的字符。
下边是utf的BOM:
UTF-8 ║ EF BB BF
UTF-16LE ║ FF FE
UTF-16BE ║ FE FF
UTF-32LE ║ FF FE 00 00
UTF-32BE ║ 00 00 FE FF
这个字节序不要出现在传输中,例如:在进行组包发送数据时,当字符使用utf-8编码时,会多出BOM,所以要先截除BOM,然后进行传输,这点是要注意的。对于utf-8编码的字符,要向前截除3个字节。
下面再看一下UTF-8编码的16进制。还是“赵”字。在记事本中添加“赵”字,编码选择utf-8,然后在ultra中打开,切换到16进制模式,之前,先看一下这个字在程序中的utf-8编码下的16进制情况:
16进制:E8B5B5
现在提供一下编码的16进制查看方法:
{
byte[] bb = encoding.GetBytes(selfChar);
bb=bb.Reverse().ToArray();
string strTemp = string.Empty;
foreach (byte b1 in bb)
{
strTemp += Convert.ToInt32(b1.ToString()).TransCoding(eType);
}
return strTemp;
}
这个方法是连着上边的进行的。
在utf-8下的的记事本上,“赵”字的全16进制格式是:EF BB BF E8 B5 B5
其中后3个字节是“赵”字的utf8编码,而前三个字节就是BOM了。
再来看一下,utf-8的编码格式:
000000 - 00007F ║ 0xxxxxxx
000080 - 0007FF ║ 110xxxxx 10xxxxxx
000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
在0-7F之间用的一个字节。与Ascii码对应。7F就是10进制的127。
在128-2047之间用2个字节。
在2048-65535之间用3个字节。
在65536-1114111之间用4个字节
而unicode与utf-8之间的转换怎么样的?还以上表为例子,例如:“赵”字,
它的16进制unicode编码是:8D75,它在第三行也就是2048-65535之间。
000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
然后,8D75的二进制表示为(用计算器转一下):1000110101110101
然后,用这些二进制从低位向高位(从右向械)依次取6位:
1000-110101-110101
然后替换x,如果不够位数,则高位用0补,然后得到的二进制是:
11101000-10110101-10110101
然后,这3个字节的16进制就是:E8 B5 B5
然后再以字母M来试一下,因为这个字母是Ascii码表中的值(这样说不太准确),或者说它是127之内的值,所以utf-8编码格式与ascii一样。(尽管如此,做为utf-8编码,文本串最前边还是多出3个字节,BOM)
现在再找一个字:“李”,它的unicode编码值是: 674E
它的范围在:000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
这个范围内,然后,这2个字节的二进制是:110011101001110,然后由低位向高位按6位取:
110-011101-001110,不足4位的高位用0补:0110-011101-001110,然后替换x就是:
11100110-10011101-10001110,16进制数是:E69D8E
在ultra中可以验证一下:utf-8全文:EF BB BF E6 9D 8E
现在通过程序来实现一下Unicode到utf-8的转换(通过移位来进行)
准备工作:参照:1110xxxx 10xxxxxx 10xxxxxx 其中的X用0替换,表示为:
11100000 10000000 10000000
然后,一个unicode编码的字符是2个字节,就是16位,而utf-8编码(这里还以汉字为例)是3个字节
string str="赵";
int k = int.Parse(str.GetUnicode(new UnicodeEncoding(), eTrans.Decimal));
byte[] bb = _unicoding.GetBytes(str);
先得到“赵”字的unicode值和字节。
11100000 10000000 10000000
这三个字节,会16进制表示为:0xE0,0x80,0x80
这个字的unicode的编码的二进制表示为:1000-110101-110101
先算第一个字节:
第一个字节为0xE0与上1000(二进制),而1000可以是“赵”字的unicode编码右移12位,所以:
_list.Add(0xe0|k1);
第二个字节是0x80与上110101,
而110101是“赵”字的unicode编码右移6位,变为:1000-110101,然后与上111111就可以了,而111111的16进制为:0x3F,所以:
_list.Add(0x80 | k2);
第三个字节是0x80与上110101,
110101是“赵”字的unicode的后6位,所以与上6个1就可以了,所以:
_list.Add(0x80 | k3);
结果是:
232|181|181
E8|B5|B5
转载于:https://www.cnblogs.com/jams742003/archive/2010/03/25/1695421.html
字符编码(1)——Unicode,utf-8相关推荐
- 记事本字符编码没有Unicode选项
记事本字符编码没有Unicode选项 Windows 10更新1903版本后,记事本的几种编码模式改了名称: 旧版的"Unicode"相当于新版的"UTF-16 LE&q ...
- 关于JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换
出处: https://www.cnblogs.com/haimishasha/p/6117968.html 目录 1.1. ISO-8859-1 通常叫做Latin-1 1.2. GB2312/GB ...
- 字符编码、Unicode原理、数据流压缩Zlib与Miniz的实现
字符集和字符编码的区别和联系 字符集:多个字符的集合.例如 GB2312 是中国国家标准的简体中文字符集,GB2312 收录简化汉字(6763 个)及一般符号.序号.数字.拉丁字母.日文假名.希腊字母 ...
- 计算机字符编码及Unicode简介(转)
计算机,毫无疑问是一部机器,在最初我们接触计算机时或者接收计算机教育时,我们就知道:计算机能识别的只有0和1组成的二进制编码.人与计算机交互早期也是用二进制编码方式,当时人们或通过扳动计算机庞大的面板 ...
- 字符编码 ansi unicode utf-8 区别
简介 为使计算机支持更多语言,通常使用 0x80~0xFFFF 范围的 2 个 字节来表示 1 个字符.比如:汉字 '中' 在 ANSI编码 中文操作系统中,使用 [0xD6,0xD0] 这两个字节存 ...
- 字符编码:ASCII,Unicode(UTF-8)
1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte). ...
- 字符编码 ASCII,Unicode和UTF-8的关系
转自:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143166410626 ...
- 【拓展】谈谈字符编码:Unicode编码与emoji表情编码
" 开发过程中,字符编码是我们一定要掌握的知识.本文回顾ASCII标准,并介绍了Unicode和UTF-8.UTF-16方案间的关系,各自是如何存储的,最后介绍了Unicode中emoji表 ...
- 字符编码、unicode、代码页、矢量字体及多国语开发
无辜的"联通": 在windows下打开一个记事本,输入"联通"保存后,再次打开却发现"联通"不见了 首先了解,不同编码文本的存储,开头字节 ...
- 字符编码:Unicode和UTF-8之间的关系
Unicode和UTF-8之间的关系 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256 ...
最新文章
- mysql行格式化_MySQL数据格式化语句
- android 常用的监听器,Android中的Keyboard监听事件
- SQL Server数据库中批量导入数据的四种方法总结
- python桌面图形_Python桌面图形程序美化的方法论
- Charles+Android模拟器里抓http请求(配置模拟器教程)
- hive 语句总结_Hive常用命令总结
- php mysql 地理位置_PHP MySql和地理位置
- asp.net 取windows的所有进程
- go-import下划线的作用
- html2canvas截图地图和看到的不一样_大秦赋,我看到的不一样的赢异人。
- [Windows Phone] 自己动手实现Telerik公司的LayoutTransform动画效果
- PC蓝牙加串口调试助手调试蓝牙设备
- arp表老化时间及其修改
- flashfxp3.41中文版注册码:(适合最新版本)
- 正宗eMule官方网站导航
- 矢量数据 秦岭淮河_秦岭-淮河一线的大致纬度
- 牛蛙怎么做好吃 牛蛙的家常做法
- SEON - 1 怒怼Dp(1)
- 【面试利器】 原生JS灵魂拷问,你能答上多少(一)
- 图像DFT和DCT的频域真实频率