Unicode
起源与发展
Unicode是为了解决传统的字符编码方案的局限而产生的,例如ISO 8859所定义的字符虽然在不同的国家中广泛地使用,可是在不同国家间却经常出现不兼容的情况。很多传统的编码方式都有一个共同的问题,即容许电脑处理双语环境(通常使用拉丁字母以及其本地语言),但却无法同时支持多语言环境(指可同时处理多种语言混合的情况)
在文字处理方面,统一码为每一个字符而非字形定义唯一的代码(即一个整数)。换句话说,统一码以一种抽象的方式(即数字)来处理字符,并将视觉上的演绎工作(例如字体大小,外观形状,字体形态,文体等)留给其他软件来处理,例如网页浏览器或者是文字处理器
目前,几乎所有电脑系统都支持基本拉丁字母,并各自支持不同的其他编码方式。Unicode为了和它们相互兼容,其首256字符保留给ISO 8859-1所定义的字符,使既有的西欧语系文字的转换不需要特别考量;并且把大量相同的字符重复编到不同的字符中去,使得旧有纷杂的编码方式得以和Unicode编码间互相直接转换,而不会丢失任何信息。
Unicode的编码
统一码的编码方式与ISO 10646的通用字符集概念相对应。目前实际应用的统一码版本对应于UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示65536个字符。基本满足各种语言的使用。实际上当前版本的统一码并未完全使用这16位编码,而是保留了大量空间以作为特殊使用或将来扩展。
上述16位统一码字符构成基本多文种平面。最新的统一码版本定义了16个辅助平面,两者合起来至少需要占据21位的编码空间,比3字节略少。但是事实上辅助平面字符仍然占用4字节编码空间,与UCS-4保持一致
实现方式
Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称UTF)
例如,如果一个仅包含基本7位ASCII字符的Unicode文件,如果每个字符都使用2字节的原Unicode编码传输,其第一字节的8位始终为0。这就造成了比较大的浪费。对于这种情况,可以使用UTF-8编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0).而遇到与其他Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。这样对以7位ASCII字符为主的西文文档就大大节省了编码长度。类似的,对未来会出现的需要4个字节的辅助平面字符和其他UCS-4扩充字符,2字节编码的UTF-16也需要通过一定的算法进行转换。
UTF-8
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部分修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文件的应用中,优先采用的编码。
UTF-8使用一至四个字节为每个字节编码:
- 128个US-ASCII字符只需要一个字符编码(Unicode范围由U+0000至U+007F)
- 带有附加符号的拉丁文,希腊文,西里尔字母,亚美尼亚语,希伯来文,阿拉伯文、叙利亚文及它拿字母则需要二个字节编码(Unicode范围由U+0080至U+07FF)
- 其他基本多文种平面(BMP)中的字符(这包含了大部分常用字)使用三个字节编码
- 其他极少使用的Unicode 辅助平面的字符使用四字节编码
UTF-8编码字节含义
- 对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符(范围:00000000-01111111,对应10进制为0-127)
- 如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码(范围:10000000-10111111,对应10进制128 - 191)
- 如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示(范围:11000000-11011111,对应10进制192-223)
- 如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的地一个字节,并且该字符由三个字节表示(范围:11100000-11101111,对应10进制224-239)
- 如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示(范围:11110000-11110111,对于10进制240-247)
将字符串按utf-8划分成单个编码数组
public static function strSplitPhp5Utf8 ($str)
{
// place each character of the string into and array
$split = 1;
$array = array();
for ($i = 0; $i < strlen($str);) {
$value = ord($str[$i]);
// 根据UTF-8编码字节含义划分成单个编码
if ($value > 127) {
if ($value >= 192 && $value <= 223)
$split = 2;
elseif ($value >= 224 && $value <= 239)
$split = 3;
elseif ($value >= 240 && $value <= 247)
$split = 4;
} else {
$split = 1;
}
$key = null;
for ($j = 0; $j < $split; $j ++, $i ++) {
$key .= $str[$i];
}
array_push($array, $key);
}
return $array;
}