字符编码的问题看似很小,常常被技术人员漠视,然而很容易导致一些莫名其妙的问题。这里总结了一下字符编码的一些普及性的常识,心愿对大家有所帮忙。
ASCII码
美国国家标准协会ANSI制订了一个规范,规定了罕用字符的汇合以及每个字符对应的编号,这就是ASCII字符集(Character Set),也称ASCII码。
过后的计算机广泛应用8比特字节作为最小的存储和处理单元,加之过后用到的字符也很少,26个大小写英文字母还有数字再加上其余罕用符号,也不到100个,因而应用7个比特位(2^7=128)就能够高效的存储和解决ASCII码,剩下最高位1比特被用作一些通信零碎的奇偶校验。下图为ASCII码字符集:
图中,每个字符都有对应的数字,叫做码点。如A对应的码点为65。
Unicode字符集
Unicode字符集涵盖了目前人类应用的所有字符,并为每个字符进行对立编号,调配惟一的字符码(Code Point)。Unicode字符集将所有字符依照应用上的频繁度划分为17个层面(Plane),每个层面上有216=65536个字符码空间。
编码零碎的变动
在Unicode呈现之前,所有的字符集都是和具体编码方案绑定在一起的,这种形式的毛病在于,字符和字节流之间耦合得太严密了,从而限定了字符集的扩大能力。假如当前火星人入住地球了,要往现有字符集中退出火星文就变得很难甚至不可能了,而且很容易毁坏现有的编码规定。因而Unicode在设计上思考到了这一点,将字符集和字符编码方案分来到。
常见的Unicode编码
UTF-8
如图所示
- 如果一个字节的第一位为0,那么代表以后字符为单字节字符,占用一个字节的空间。0之后的所有局部(7个bit)代表在Unicode中的序号。
- 如果一个字节以110结尾,那么代表以后字符为双字节字符,占用2个字节的空间。110之后的所有局部(5个bit)加上后一个字节的除10外的局部(6个bit)代表在Unicode中的序号。且第二个字节以10结尾
- 如果一个字节以1110结尾,那么代表以后字符为三字节字符,占用3个字节的空间。110之后的所有局部(5个bit)加上后两个字节的除10外的局部(12个bit)代表在Unicode中的序号。且第二、第三个字节以10结尾
- 如果一个字节以10结尾,那么代表以后字节为多字节字符的第二个字节。10之后的所有局部(6个bit)和之前的局部一起组成在Unicode中的序号。
utf-8的益处是
- 反对ascii:一个utf-8遍码的英文文本用ascii读取没有任何问题
- 节约空间:utf-8让unicode里码点小的字符也相应领有更短的长度
UCS-2/UTF-16
如果要咱们来实现Unicode字符集中BMP字符的编码方案,咱们会怎么实现?因为BMP层面上有216=65536个字符码,因而咱们只须要两个字节就能够齐全示意这所有的字符了。
举个例子,“中”的Unicode字符码是0x4E2D(01001110 00101101),那么咱们能够编码为01001110 00101101(大端)或者00101101 01001110 (小端)。
UCS-2和UTF-16对于BMP层面的字符均是应用2个字节来示意,并且编码失去的后果完全一致。不同之处在于,UCS-2最后设计的时候只思考到BMP字符,因而应用固定2个字节长度,也就是说,他无奈示意Unicode其余层面上的字符,而UTF-16为了解除这个限度,反对Unicode全字符集的编解码,采纳了变长编码,起码应用2个字节,如果要编码BMP以外的字符,则须要4个字节结对,这里就不探讨那么远,有趣味能够参考维基百科。
Windows从NT时代开始就采纳了UTF-16编码,很多风行的编程平台,例如.Net,Java,Qt还有Mac下的Cocoa等都是应用UTF-16作为根底的字符编码。例如代码中的字符串,在内存中相应的字节流就是用UTF-16编码过的。
锟斤拷
锟斤拷是常见的中文乱码,常见到了有了知名度
unicde字符集有一个非凡的替换符号,专门用于展现无奈辨认或展现的字符,如图所示:
有些编辑器在编码为utf-8时会把无奈辨认或者展现的字符主动替换为这个替换符号,用于提醒用户。
而如果用户点击了保留,它在utf-8编码后则是3字节长度的二进制数字。
2个问号字符连在一起,把文件再用GBK编码读取,关上后就会看到以前是2个替换符号的中央当初都变成了锟斤拷。
参考
- 对于字符编码,你所须要晓得
- 你懂乱码吗?锟斤拷烫烫烫(详解ASCII、Unicode、UTF-32、UTF-8编码)
- [十分钟搞清字符集和字符编码](
发表回复