字符编码的问题看似很小,往往被技术人员忽视,却很容易导致一些莫名其妙的问题。这里总结了一些字符编码的科普知识,希望对大家有所帮助。ASCII码美国国家标准协会ANSI制定了一个标准,规定了常用字符的集合和每个字符对应的编号。这就是ASCII字符集(CharacterSet),也称为ASCII码。当时的计算机一般以8位字节作为最小的存储和处理单位,当时使用的字符很少。26个大小写英文字母和数字加上其他常用符号不足100个,所以使用7位(2^7=128)可以高效存储和处理ASCII码,剩下的1位用作奇偶校验对于某些通信系统。下图为ASCII码字符集:图中,每个字符都有一个对应的编号,称为码点。例如A对应的codepoint是65。Unicode字符集Unicode字符集涵盖了目前人类使用的所有字符,并对每个字符统一编号,并赋予一个唯一的字符编码(CodePoint)。Unicode字符集根据使用频率将所有字符分为17个级别(Plane),每个级别有216=65536个字符编码空间。编码系统的变化在Unicode出现之前,所有的字符集都绑定了一个特定的编码方案。这种方式的缺点是字符和字节流耦合太紧,限制了字符集的扩展能力。假设未来火星人生活在地球上,将火星字符添加到现有字符集中将变得困难甚至不可能,并且很容易打破现有的编码规则。所以Unicode在设计时就考虑到了这一点,将字符集和字符编码方案分开。常见的Unicode编码UTF-8如图所示。如果一个字节的第一位为0,则表示当前字符为单字节字符,占用一个字节的空间。0之后的所有部分(7位)代表Unicode中的序号。如果一个字节以110开头,则表示当前字符为双字节字符,占用2个字节的空间。110(5位)之后的所有部分加上下一个字节除10(6位)以外的部分都表示Unicode中的序号。而第二个字节以10开头,如果一个字节以1110开头,则表示当前字符是一个三字节字符,占用3个字节的空间。110(5位)之后的所有部分加上除10(12位)之外的最后两个字节表示Unicode中的序号。而第二个和第三个字节以10开头。如果一个字节以10开头,则表示当前字节是一个多字节字符的第二个字节。10(6位)之后的所有部分和前面的部分一起构成了Unicode中的序列号。utf-8的优点是它支持ascii:一个utf-8编码传递的英文文本用ascii读取是没有问题的。节省空间:utf-8让unicode中码位小的字符对应的长度更短UCS-2/如果UTF-16要求我们实现Unicode字符集中BMP字符的编码方案,我们将如何实现呢?由于BMP级别有216=65536个字符编码,我们只需要两个字节就可以完整表示所有这些字符。例如“中”的Unicode字符编码为0x4E2D(0100111000101101),那么我们可以将其编码为0100111000101101(大端)或者0010110101001110(小端)。UCS-2和UTF-16都是用2个字节来表示BMP级别的字符,编码结果是完全一致的。不同的是,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个替换符号的地方现在变成了副本。参考关于字符编码,你需要知道的你了解乱码吗?Kunjincopyinghothothot(ASCII、Unicode、UTF-32、UTF-8编码详解)【十分钟搞定字符集和字符编码】(
