renpeng2049.github.io

renpeng2049的个人博客

字符编码汇总

coding过程中,经常会遇到字符编码问题,有一些共性的问题,记录如下。

Unicode与utf-8

unicode是一个编码规范,它纳入了世界上所有的字符,赋予每个字符一个唯一编码。如一个汉字在unicode里对应一个2字节编码,这个编码在支持unicode的系统里都能被正确识别。

单从编码规范的角度来看,unicode跟计算机(可以)没有任何关系。

unicode定义了字符的编码(码值),但是并未定义计算机中该如何存储、传送内容,所以,出现了UTF(unicode transformation format),有UTF-8和UTF-16。UTF-16即任何字符都用两个字节存放,这对英文为主的环境显然太浪费,但是对中文为主的环境比较适合。UTF-8是变长编码(1到3字节),解决了浪费问题,缺点是编码规则复杂一些。

utf-8表示形式

utf8根据当前字节的第一个bit来确定使用几个字节来表示(存储)一个unicode,这是约定的规则.你用UTF-8来表示时必须遵守这样的规则.我们知道UTF-16不需要用啥字符来做标志,所以两字节也就是2的16次能表示65536个字符.而UTF-8由于里面有额外的标志信息,所有一个字节只能表示2的7次方128个字符,两个字节只能表示2的11次方2048个字符.而三个字节能表示2的16次方,65536个字符.由于”汉”的编码27721大于2048了所有两个字节还不够,只能用三个字节来表示.

0xxxxxxx,如果是这样的01串,也就是以0开头后面是啥就不用管了XX代表任意bit.就表示把一个字节做为一个单元.就跟ASCII完全一样. 110xxxxx 10xxxxxx.如果是这样的格式,则把两个字节当一个单元 1110xxxx 10xxxxxx 10xxxxxx 如果是这种格式则是三个字节当一个单元.

所有要用1110xxxx 10xxxxxx 10xxxxxx这种格式.把27721对应的二进制从左到右填充XXX符号,于是就出现了Big-Endian,Little-Endian的术语.Big-Endian就是从左到右,Little-Endian是从右到左. 由上面我们可以看出UTF-8需要判断每个字节中的开头标志信息,所以如果一当某个字节在传送过程中出错了,就会导致后面的字节也会解析出错.而UTF-16不会判断开头标志,即使错也只会错一个字符,所以容错能力强.

如何区分文件是那种类型

前面说了要知道具体是哪种编码方式,需要判断文本开头的标志,下面是所有编码对应的开头标志

开头标识 编码方式
EF BB BF UTF-8
FE FF UTF-16/UCS-2, little endian
FF FE UTF-16/UCS-2, big endian
FF FE 00 00 UTF-32/UCS-4, little endian
00 00 FE FF UTF-32/UCS-4, big-endian

其中的UCS就是前面说的ISO制定的标准,和Unicode是完全一样的,只不过名字不一样.ucs-2对应utf-16,ucs-4对应UTF-32.UTF-8是没有对应的UCS