X

曜彤.手记

随记,关于互联网技术、产品与创业

UCS-2 编码的妙用

我们在日常的开发当中经常会碰到诸如 UTF-8、UTF-16 等字符编码方式,其实这些字符编码方式都是 Unicode 编码的一种实现方式。而今天我们的主角就是Unicode 编码的另一种实现方式 - “UCS-2” 编码。借助于 “UCS-2” 编码,我们可以实现一些相对“特殊”的需求。

在介绍 “UCS-2” 之前,我们先来复习一下 Unicode 编码的相关知识。Unicode 编码是一种可以容纳全世界所有语言文字的编码方案。Unicode 使用一个确定的名字和一个叫做“码位”的十六进制数来定义一个字符。例如字符 “A” 对应的 Unicode 码位为 0x0041(十进制整数为65)的码位。而实际上 Unicode 编码的码位从 u0000(0x0000)到 u007F(0x007F)与 ASCII 完全一致。

Unicode 的码空间范围从 u0000(0x0000)到 u10FFFF(0x10FFFF),共有“1,112,064”个码位可用来映射字符. 而其中码位从 u0000 至 uFFFF 的范围内包含了最常用的字符,这一部分被称为基本多语言平面(Basic Multilingual Plane),缩写为 BMP。处于其他范围的码位则称为辅助平面(Supplementary Planes)。

UCS-2 英文全称为 “2-byte Universal Character Set”,而相对 UTF-8(变长编码)不同,它是一种定长的编码方式,UCS-2 仅仅简单的使用一个16位码元来表示码位,也就是说它可以表示 Unicode 编码从 u0000 到 uFFFF 码位范围内的所有字符。但请记住,UCS-2 只是一种 Unicode 编码的具体实现方式。

那么,我们可以拿 “UCS-2” 编码来做些什么呢?因为 “UCS-2” 在码位范围 u0000 到 uFFFF 范围内的编码与 Unicode 的码位完全一致,因此我们用这一特性来进行对字符的“语言识别”。通过判断某一字符的 UCS-2 编码的码位值(16进制值)其大小,可以判断该字符是属于那一语言或语系。比如汉语的 USC-2 编码码位范围为 u4E00(0x4E00)到 u9FFF(0x9FFF),其他语系也以此类推拥有其对应的码位范围。

下面给出基于 PHP的实现代码:(此段代码会自动分析用户输入字符串内的所有字符的所属语言体系)

class Util {
  public static function charAnaylze($str) {   
    // 转换成 UCS-2 定长编码;
    $str = iconv('UTF-8', 'UCS-2', $str);

    // 获取字符串总长度;
    $strLen = strlen($str);

    $tempStr = '';
    $resultArr = array();

    // 每次处理一个字符;
    for ($i = 0; $i < $strLen - 1; $i = $i + 2) {
      $lowByte = $str[$i];
      $highByte = $str[$i + 1];

      // 按位转换并填充;
      $lowByteEncoded = str_pad(base_convert(ord($lowByte), 10, 16), 2, 0, STR_PAD_LEFT);
      $highByteEncoded = str_pad(base_convert(ord($highByte), 10, 16), 2, 0, STR_PAD_LEFT);
      $hexStr = $lowByteEncoded . $highByteEncoded;
      $value = hexdec($hexStr);

      // 创建临时字符;
      $tempStr = iconv('UTF-8', 'UCS-2', "A");
      $tempStr[0] = $lowByte;
      $tempStr[1] = $highByte;

      // 编码;
      $char = iconv('UCS-2', 'UTF-8', $tempStr);
      
      if($value >= 65 && $value <= 122) {
        // Latin 字母;
        $resultArr['Latin字母'][] = $char;
      }

      if($value >= 48 && $value <= 57) {
        // Latin 数字;
        $resultArr['Latin数字'][] = $char;
      }

      if(($value >= 33 && $value <= 47) || ($value >= 58 && $value <= 64)) {
        // Latin 符号;
        $resultArr['Latin符号'][] = $char;
      }

      if(($value >= 1536 && $value <= 1791)) {
        // 阿拉伯语;
        $resultArr['阿拉伯语'][] = $char;
      }

      if(($value >= 19968 && $value <= 40959)) {
        // 汉字;
        $resultArr['汉字字符'][] = $char;
      }
    }

    return $resultArr;
  }
}



评论 | Comments


Loading ...