Unicode in JavaScript

Unicode in JavaScript

by Jinya

【转载请注明出处,http://blog.csdn.net/EI__Nino】 

名词解释:

 

BMP:(BasicMultilingual Plane)它又简称为"零号平面", plane 0

 

UCS:通用字符集(Universal Character Set, UCS)

 

ISO:国际标准化组织(ISO)

 

UTF:UCS Transformation Format,

 

BOM:Byte Order Mark 字节序

 

CJK: 统一表意符号 (CJK Unified Ideographs)

 

BE:Big Endian 大端

 

LE:Little Endian 小端

 

 

 

一、简介

 

Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。

 

二、UCS

 

通用字符集(UniversalCharacter Set, UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。UCS-2用两个字节编码,UCS-4用4个字节编码。

 

UCS-4根据最高位为0的最高字节分成27=128个group。每个group再根据次高字节分为256个平面(plane)。每个平面根据第3个字节分为256行 (row),每行有256个码位(cell)。group 0的平面0被称作BMP(Basic MultilingualPlane)。如果UCS-4的前两个字节为全零,那么将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。

 

三、Unicode

 

Unicode标准准备把康熙字典的所有汉字放入到Unicode 32bit编码中。

 

Unicode扩展自ASCII字元集。在严格的ASCII中,每个字元用7位元表示,或者电脑上普遍使用的每字元有8位元宽;而Unicode使用全16位元字元集。这使得Unicode能够表示世界上所有的书写语言中可能用於电脑通讯的字元、象形文字和其他符号。Unicode最初打算作为ASCII的补充,可能的话,最终将代替它。考虑到ASCII是电脑中最具支配地位的标准,所以这的确是一个很高的目标。

Unicode影响到了电脑工业的每个部分,但也许会对作业系统和程序设计语言的影响最大。从这方面来看,我们已经上路了。Windows NT从底层支持Unicode(不幸的是,Windows 98只是小部分支援Unicode)。先天即被ANSI束缚的C程序设计语言通过对宽字元集的支持来支持Unicode。

  

四、UTF-8

 

字节FF和FE在UTF-8编码中永远不会出现,因此他们可以用来表明UTF-16或UTF-32文本(见BOM) UTF-8 是字节顺序无关的。

 

UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:

Unicode编码(十六进制) 

UTF-8 字节流(二进制)

000000 - 00007F

0xxxxxxx   (7x)

000080 - 0007FF

110xxxxx 10xxxxxx  (11x)

000800 - 00FFFF

1110xxxx 10xxxxxx 10xxxxxx  (16x)

010000 - 10FFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  (21x)

  

 

UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,处于0号平面,BMPUTF-8编码与ASCII编码完全相同。

 

-> “\x32"
   2
 
-> "\u0032"
   "2"
 

UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。

Unicode的最大码位0x10FFFF也只有21位。

例1:"汉"字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。

将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

 

-> encodeURI(“汉")
   “%E6%B1%89"

 

例2:Unicode编码0x20C30在0x010000-0x10FFFF之间,使用用4字节模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。

 

五、The love between Javascript and Unicode

 

可以使用String.fromCharCode 方法从任意进制的数字转成字符串

\u加一个十六进制数字可以转成字符串

 

 

-> String.fromCharCode("0x4e01")
    "丁"
 
-> 0x4e01.toString(10)
   "19969"
 
-> String.fromCharCode(19969)
    "丁"
 
-> "0x4e01".toString()
   "0x4e01"
 
-> "\u4e01".toString()
    “丁"
-> "\u4e01".toString()
    "丁"
 

 
六、输出

 

输出 "\u4e01"

 

->eval('"\u4e01"')
    "丁"
==
"\u4e01" -> "丁" ->eval(‘"丁"’)
 
 
->eval('"\\u4e01"')
    "丁"
==
"\\u4e01" -> "\u4e01" ->eval(‘"\u4e01"’)
 
 
-> eval('"\\\u4e01"')
    "丁"
==
"\\\u4e01" -> "\丁" ->eval(‘"\丁"’)
 
-> eval('"\\\\u4e01"')
    "\u4e01"
==
"\\\\u4e01" -> "\\u4e01" ->eval(‘"\\u4e01"’)
 
 
 
->'\u4e01'
    "丁"
 
->'\\u4e01'
   "\u4e01"
 
->'\\\u4e01'
    "\丁"
 
->'\\\\u4e01'
   "\\u4e01"

 

输出 "\丁"

-> "\丁"
    "丁"
 
-> "\\丁"
    "\丁"
 
-> "\\\丁"
    "\丁"
 


 

七、BOM

 

字节序有两种,分别是“大端”(Big Endian, BE)和“小端”(Little Endian, LE)。

根据字节序的不同,UTF-16可被实现为UTF-16LE或UTF-16BE,UTF-32可被实现为UTF-32LE或UTF-32BE。例如:

Unicode编码

 

UTF-16LE

UTF-16BE

 

UTF32-LE

UTF32-BE

 

0x006C49

49 6C

 

6C 49

 

49 6C 00 00

 

00 00 6C 49

 

0x020C30

 

43 D8 30 DC

 

D8 43 DC 30

 

30 0C 02 00

 

00 02 0C 30

 

Unicode标准建议用BOM(Byte Order Mark)来区分字节序,即在传输字节流前,先传输被作为BOM的字符“零宽无中断空格”。这个字符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定义的码位,不应该出现在实际传输中。

下表是各种UTF编码的BOM:

UTF编码

Byte Order Mark (BOM)

 

UTF-8 without BOM

UTF-8 with BOM

EF BB BF

UTF-16LE

FF FE

UTF-16BE

FE FF

UTF-32LE

FF FE 00 00

UTF-32BE

00 00 FE FF

 

八、讨论

 

为什么中文会占3个字节?

 

中文范围 4E00-9FBF:CJK 统一表意符号 (CJK Unified Ideographs)

unicode 编码 000800 - 00FFFF 内的UTF-8 二进制表示为:1110xxxx 10xxxxxx 10xxxxxx 。

 

英文是在ASCII里可以表示,而ASCII编码的表示和UTF-8编码完全相同。他们的范围在0x00-0x7F之间。

unicode 编码 000000 - 00007F 内的UTF-8 二进制表示为:0xxxxxxx    。

 

 

随机获取中文?

 

-> 0x4e00.toString(10)
    19968
-> 0x9FBF.toString(10)
       40895
->  40895-19968
     20927
 
   String.fromCharCode(19968+Math.round(Math.random()*20927)


 

是否需要 BOM 头 ?

 

它的字节顺序在所有系统中都是一样的,因此它实际上并不需要BOM。但是PHP中,session创建前需要无输出,所以一般utf-8编码的php文件都要去除Bom头

 

HTML中的Unicode 和 javascript表示方法一样吗?

 

“&#” + unicode数字 得到对应的字符

 

document.write(“丁”)   => 丁

document.write(“一”)   =>丁

 

怎样查找中文? 

-> “么么哒,memda".match(/[\u4e00-\u9FBF]/img)
    ["么", "么", "哒"]
 

 

长度?

 
->““么".length
    1
 
->"\u4e01".length
    1
 

怎么从汉字获取到unicode编码?

 
-> “么”.charCodeAt(0).toString(16)
    "4e48"
 
 
-> var a = “么么哒,meme”
-> a.replace(/[\u4e00-\u9fbf]/img,function($){return "\\u"+$.charCodeAt(0).toString(16); })
    "\u4e48\u4e48\u54d2,meme"
 
 
-> parseInt(encodeURI(“丁").split("%").slice(1).map(function(v){return parseInt(v,16).toString(2).replace(/^1*0/,”"); }).join(""),2).toString(16)
   “4e01"
==
encodeURI(“丁”) => “%E4%B8%81" =>[“E4”,”B8”,”81”] => ["0100","111000", “000001"]
 
=>”0100111000000001”=> 19969 =>”4e01"
 

 

 

参考:

 

https://github.com/chenjinya/matrix

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。