现在的位置: 首页 > 综合 > 正文

汉字字符编码的科普笔记(GB2312汉字编码,Unicode与UTF-8,字符映射表,vim,文泉驿,正则表达式)

2013年08月05日 ⁄ 综合 ⁄ 共 8623字 ⁄ 字号 评论关闭

 GB2312与cp936

1. GB2312简介

GB2312GB2312-80,诞生于1981年,共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符,共7445个字符。GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。用区位码表示。范围:区(01-87),位(01-94)。

2. Code Page

Windows中使用VIM打开一个以GB2312方式编码的文档时,file encoding显示的是“cp936”。在Windows中,code
page指的就是字符集,在其他操作系统中称为字符编码(character encodings),两者是同一概念。code pages8090年代的Windows操作系统中使用,当Windows实现了Unicode时,code
pages就逐渐被取代。Code Page这个词来源于IBM的基于EBCDICmainframe系统,但包括微软、SAPOracle在内的很多制造商都使用这个说法。

另一个很奇怪的事情是,同样一份以GB2312编码的文档,在Windows里用VIM打开,就显示为cp936编码;在Linux里打开时却显示为utf-8编码,而不是“cp936”的unix说法“euc-cn”!但是以十六进制方式查看,发现文字确实是以GB2312编码的。可能是vimrc里不知道哪儿写错了。具体情况请见VIM的帮助文档“:h
encoding-values”。

3. GB2312的编码

每个汉字及符号以两个字节来表示,高位字节使用了0xA1-0xF7;低位字节使用了0xA1-0xFE 由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0-0xF7,“低位字节”的范围是0xA1-0xFE

Unicode出现后,GB2312的全部7445个字符都在Unicode的覆盖范围之内,并分布在U+00A4U+FFE5之间。另外,GB2312的常用汉字按拼音排列,次常用汉字按笔画排列,因此与Unicode的汉字部分的字序是不同的。

二 GBK(Chinese Internal Code Specification)

1. 简介

GBK诞生于1993年的Unicode 1.1版之后。之前的GB2312-80只有6763个汉字,且很多汉字在1981年之后才得到简化,故中国大陆制定了等同于Unicode
1.1版的“GB 13000.1-93”,收录中国大陆、台湾、日本、韩国的通用字符集,共20902个汉字。微软利用GB 2312-80未使用的编码空间,收录GB 13000.1-93全部字符制定了GBK编码。最早实现于Windows
95简体中文版。虽然GBK收录GB 13000.1-93的全部字符,但编码方式并不相同。以下为GBK的双字节编码示意:

2. 编码

字符有一字节和双字节编码,00-7F范围内是一位,和ASCII保持一致,此范围内严格上说有96个文字和32个控制符号。双字节中,第一字节的范围是81-FE(也就是不含80FF),第二字节的一部分领域在40-FE,其他领域在80-FE

三 GB18030

1. 简介

最新版本为GB 18030-2005,与GB 2312-1980完全兼容,与GBK基本兼容,支持GB 13000Unicode的全部统一汉字,共收录汉字70244个。与UTF-8 相同,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,收录范围包含繁体汉字以及日韩汉字。

2. 编码

单字节部分,收录了GB/T 11383-19890x000x7F全部128个字符;双字节部分:GB
13000.1-1993的全部CJK统一汉字字符等,其首字节码位从0x810xFE,尾字节码位分别是0x400x7E0x800xFE。;四字节部分:收录了上述双字节字符之外的,GB
13000CJK统一汉字扩充ACJK统一汉字扩充B和已经在GB 13000中编码的中国少数民族文字的字符,采用0x300x39作为对双字节编码的扩充的后缀。这样扩充的四字节编码,其范围为0x813081300xFE39FE39。四字节字符的第一个字节的编码为0x810xFE;第二个字节的编码范围为0x300x39;第三个字节编码范围为0x810xFE;第四个字节编码范围为0x300x39

四 Unicode

1. Unicode中的scripts

Unicode中的script指的是一种或多种书写系统中,用来代表文字信息的一个字符或其他书写符号的集合。例如,俄语和乌克兰语分别是西里尔script的不同子集。有些script支持且仅支持一种书写系统和语言,如亚美尼亚script;另一些scripts支持多种不同的书写系统,如Latin
script支持英语、法语、德语、意大利语、越南语和拉丁语。有些语言使用多种不同的书写系统,因此也使用若干个scripts。在土耳其语中,阿拉伯语的script20世纪之前使用,但到20世纪早期则转变为Latin
script。汉字书写系统使用在以下语言中:普通话、吴语、粤语、闽语(译者注:台语)、湘语、客家语、赣语、晋语、徽州语、广西平语、侗语、白语(已废弃)、苗语(已废弃)、壮语(已废弃)、日语、韩语(已废弃,只使用于学术文本和报纸中),越南语(用于历史文献、学术文献或出于艺术与审美的考虑)及其他已经失传的语言(契丹文、女真文、西夏文)。

scripts相补充的是Unicode symbolsScriptssymbols覆盖了所有的Unicode字符,统一发音符号和统一标点符号字符经常具有内在的script属性,但是单独的script常常也具有自己的发音符号和标点符号。所以很多script不仅包括字母,也包括发音符号和其他标记、标点符号、数字甚至其自己的特异性的符号和空白字符。

下图分别为以Script为单位和以区块为单位划分Unicode字符。

 

关于CJK统一表意文字(Han ideographic characters):Unicode标准中的“统一表意文字”的说法是西文中一个传统词语,尽管专业语言学家更喜欢“Sinogram”这个词。字面上说,ideograph只适用于某些古代的、原始的汉字形式,这些字的确是来源于表意描述。但绝大部分汉字是后来经组合、假借和其他非表意性的原则发展而来的,但“Han
ideographs”这个说法仍在英文中沿用。

2. Unicode平面(Plane

Unicode将代码点(Code Point)分为17个平面,其中第0个平面(基础多语言平面,Base Multilingual Plane)包含代码点0x0000-0xFFFF,第1个平面包含0x10000-0x1FFFF,以此类推。其实第0平面已经包含了绝大部分各种语言的常用字符,位置空间分布示意图如下(左上角为原点,格子中的两位十六进制数表示高位字节):

包含汉字(Han ideographs)的区块有:

  • CJK统一表意文字(4E00-9FFF):常用汉字
  • CJK统一表意文字扩展A3400-4DBF):罕用汉字
  • CJK统一表意文字扩展B20000-2A6DF):罕用汉字
  • CJK统一表意文字扩展C2A700-2B73F):罕用汉字
  • CJK兼容表意文字(F900-FAFF):重复字符,可统一的异形字
  • CJK兼容表意文字补充(2F800-2FA1F):可统一的异形字

五 UTF-8

1. 简介

全称UCS Transformation Format – 8-bit,是一种对Unicode的多字节编码。与UTF-16UTF-32类似,UTF-8可以表示Unicode字符集中的每个字符。与它们不同的是,UTF-8ASCII是向后兼容的,并且避免了尾数(endianness)的复杂性。鉴于各种原因,UTF-8已成为www最重要的字符编码,涉及超过半数网页。UTF-8使用14个字节对Unicode字符集中的1,112,064个代码点中的每一个进行编码。具体而言,使用1-3个不等的字节数编码Unicode的第0个平面。数值较低的代码点使用较少的字节数,使得编码体系较为高效。注意,Unicode对所有字符进行编码,完成从字符到代码点(如0x4E00)的映射,而与字符的具体表示无关;UTF-8完成由编码到内在表示(字节码)的映射,而不关心某个编码具体代表哪个字符。

2. 编码范围

Unicode字符集的前128个字符与ASCII码保持一对一关系,使用一个字节进行编码,使得有效的ASCII文本在UTF-8编码的Unicode下仍然有效。理论上,UTF-8可以至多编码231次方个字符(即Universal字符集起草时的理论上限)。

3. 编码规则

如果一个字符用一个字节编码,则最高位是0,其他位给出编码值(0127);

如果一个字符用kk>=2)个字节编码,则第一个字节的前k位为1,接着是一个0。随后的(k-1)个字节全部由“10”开头。所有字节的剩余位连接起来,形成了Unicode代码点值,从0x800x10FFFF。由此可见:

1)一个以0开头的字节表示单字节字符

2)一个以11开头的字节表示一个多字节字符的开头

3)一个以10开头的字节表示一个多字节字符的非开头

这样设计使得任何一个字节序列都可以被识别,并不需要从字符串的头部开始。另外由图可见,UTF-8其实是使用1-6个字节来代表一个字符的,即可以表示到0x7FFFFFFF,但是据说为了与UTF-16兼容,最高的若干位没有用,只用到0x10FFFF

以下面这个文档为例,文档以UTF-8编码。

使用16进制方式显示,如图:

分析如下:

1)在UTF-8中,单个字母是用一个字节表示的,如A表示为0x41(十进制的65),以此可以定位到汉字“一”被表示为三个字节:0xe4,
0xb8, 0x80

2)汉字“一”是UnicodeCJK统一表意文字区的第一个字符,Unicode码为0x4e00,既然表示为三个字节,则使用“1110xxxx
10xxxxxx 10xxxxxx”的模板,把4e00这十六位编码套进去,正好就是“e4 b8 80”;

3fileformatunix,因此换行符是一个<NL>,即0x0a

4)上述文档在Ubuntu里说大小为29 bytes,数一数的确如此。

六 文泉驿

1. 简介

作为几千年中华文明的见证,浩瀚传统文化传承的载体,汉字是让我们每一个中国人引以为豪的东方文明标志之一。我们的祖先创造汉字,书写汉字,利用汉字和汉语的无穷魅力创造出让人叹为观止的文学、艺术。而今天进入了计算机时代的我们,虽然不再象古人一样手持毛笔,批著简帛,但我们的生活仍然无时无刻离不开汉字。

可以毫不夸张的讲,汉字是世界上已知的最为庞大的符号系统。早在殷商时期,我们的先人就创造出了数目巨大的甲骨文,从上万片发掘的甲骨中整理出来的单字就有四千余个。东汉许慎编撰的“说文解字”,收录汉字9,353个。至清朝康熙年间,由段玉裁等人收集整理的“康熙字典”收录汉字竟达 47,035 之多。加上少数民族文字,各种古代典籍上曾经出现但并未广泛使用的古汉字和异体字,汉字总数多达十万以上。作为现代计算机系统通用编码的统一码(Unicode)在最新发布的5.2版中共收录汉字(包括简体、繁体,以及日、韩、越等地区使用的汉字) 74,394 。(注:微软的中易宋体的最新版本只有42,809个字)

我们是一群致力于在计算机世界中推广汉字,丰富电子汉字资源的志愿者。我们希望通过自己无私的劳动,使得无论您在世界上任何一个角落,都可以免费地获得我们的电子汉字资源,能够流畅地通过汉字进行交流。“文泉驿”是以上述目标为宗旨而自发创建的非盈利性组织。

2. 文泉驿正黑(WenQuanYi Zen Hei

文泉驿正黑体是一个"自由字体"。该字体包含了所有常用简体中文、繁体中文所需要的汉字(最新版本包含超过27842个汉字,完整覆盖GB2312/Big5/GBK以及GB18030标准字符集)。该字体同时还包含了日文、韩文和其他几十种语言符号。除此以外,该字体还嵌入了最新版本的文泉驿点阵宋体的中英文点阵,使得屏幕汉字显示清晰锐利,易于阅读。

作为黑体中文字体,文泉驿正黑为非衬线字体,笔画对比度明显,特别适合屏幕汉字显示以及文档标题字体。

3. 文泉驿微米黑(WenQuanYi Micro Hei

文泉驿微米黑是一个"自由字体"。该字体包含了所有常用简体中文、繁体中文所需要的汉字(最新版本包含超过20932个汉字,完整覆盖GB2312/Big5以及GBK标准字符集)。该字体同时还包含了日文、韩文和其他几十种语言符号。以外,该字体还包含了高质量的Droid
Sans拉丁符号和Droid Sans Mono等宽字体,并内置HintingKerning信息。微米黑字体文件极小,特别使用于便携式电脑设备。

4. 文泉驿点阵宋体(WenQuanYi Bitmap Song

文泉驿点阵宋体是一个"自由中文字体"。该字体包含了所有常用简体中文、繁体中文,日文及韩文所需要的汉字(最新版本包含超过27842个汉字,完整覆盖GB2312/Big5/GBK/GB18030标准字符集)。该字体同时还包含了英文、日文、韩文和其他多种语言符号。该点阵字体包含五个屏幕常用字号(9pt-12pt),逾21万汉字点阵,这些点阵都经过参与者和组织者的精心设计和调整,手工优化后的汉字点阵显示清晰锐利,特别易于屏幕阅读使用。

我们目前提供下载的文泉驿点阵宋体只能够在Linux/Unix系统上使用。在Windows上使用该字体,请下载文泉驿正黑体,正黑体嵌入了所有GBK汉字点阵,在9-12pt范围内,将自动使用点阵宋体显示。

七 正则表达式

1. Unicode字符的一般正则表达式表示

支持Unicode的程序中的正则表达式通常支持\uNUM原序列,用来匹配一个具体的Unicode字符。这个数值通常是一个4位十六进制数,例如,\uC0B5的意思是“匹配编号为U+C0B5Unicode字符”,而没说具体需要比较哪些字节,因为具体的字节是由代表这个Unicode代码点的编码方式在内部决定的。如果程序内部使用的是UTF-8编码,这个字符就用3个字符表示。不过使用支持Unicode程序的用户,并不需要关心这个。

为了匹配任何一个Unicode字符,应该用\X,这相当于Unicode中的点号。在Java中,用\uFFFFFFFF是代码点)来匹配某个特定的Unicode字符。

2. PerlPCREUnicode字符的正则表达式表示

PerlPCRE中,并不支持\uFFFF这样的语法,而是使用\x{FFFF}。例如,\x{1234}不会和“匹配\x
1234次”混淆,而是永远代表U+1234这个Unicode字符;\x{1234}{5678}则代表匹配U+1234这个Unicode字符整整5678次。

PerlPCRE还是极少数的支持基于ScriptsUnicode进行匹配的正则表达式引擎!方法是\p{Script_Name}例如,\p{Bopomofo}匹配一个注音符号字母,\p{Han}匹配一个汉字。此外还支持基于区块的匹配,如\p{InCJK_Unified_Ideographs}匹配所有CJK统一表意文字区的字符(等同于U+4E00…U+9FFF

Perl中读取以UTF-8编码的文件,还有另一个问题:当使用<><FILEHANDLE>等方式读取文件时,perl会把文件视为一系列字节流,而UTF-8是变长字节编码的,想以字符(而不是字节)为单位来处理,则必须进行解码。

例如,运行如下代码

打印出来的是每行一个带问号的小菱形,说明字符串$_中每个单元是一个字节。要解决这个问题,有两种思路:一方面使用binmode改造句柄,使之以UTF-8方式读取,如下:

但是这样有个问题是第一个字符不能正常读取!之后的都正常!这是为什么啊!另一个思路是对读入的字符串进行处理,即告诉perl这个字符串(本质上是字节序列)要以UTF-8的多字节方式解析。这一过程是decode,因此用以下方法可以解决问题:

读入之后,就可以用\x{abcd}, \p{Han}\p{InCJK_Unified_Ideographs}等方式对其进行正则表达式处理了。

3. VimUnicode正则表达式的支持

         作为最强大的文本编辑器,Vim对正则表达式的支持是人尽皆知的。而且,毕竟是文本编辑器,执行个查找啊替换啊这种处理会比用perl直观得多。但是,对于Unicode字符的支持,Vim采用的正则表达式引擎却远比不上Perl(图为节选)

有人说,为什么Vim不用PCRE呢?回复说,ViPerl出来的早得多,应该问为什么Perl不跟Vi学。无论如何,在Vim里匹配Unicode字符会遇到一点麻烦:你可以用/\u4e00匹配“一”,也可以用/[\u4e00-\u4eff]匹配Unicode表中的第一行汉字(一、丁、万、三、上……),却不能用/[\u4e00-\u9fff]匹配CJK统一表意文字区块中的所有文字!不知道是不是我的使用有问题!

八 Ubuntu中的字符映射表(Character Map)

        

这是Ubuntu中相当于Windows“字符映射表”的软件,可以在Applications -> Accessories中找到。且不说以文泉驿微米黑显示的字符表有多好看,就说这个Character
Details就做得非常帅,给出的信息包括:UTF-8编码方式、XML实体表示形式、英文释义、普通话发音、广东话发音、日语发音、韩语发音!

工作过程中有时候需要看看UnicodeScripts,或者查找某个字符的Unicode码,或者要copy某种北欧语言的奇怪字符,都可以用Character
Map

        

另外,字符映射表支持根据字符查找与根据Unicode值查找:

在这两天的折腾过程中,帮了不少忙。

本来只是想解决Perl处理UTF-8中文文档的问题,不小心扯出来这么多东西。以上是这两天折腾的全部结果,折腾了24小时……没有苦劳也有疲劳啊。

九 参考资料

  • http://en.wikipedia.org/wiki/Windows_code_page
  • http://en.wikipedia.org/wiki/UTF-8
  • http://en.wikipedia.org/wiki/Plane_(Unicode)
  • http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters
  • http://en.wikipedia.org/wiki/List_of_languages_by_writing_system
  • http://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines
  • http://en.wikipedia.org/wiki/Code_pages
  • http://en.wikipedia.org/wiki/CJK_Unified_Ideographs
  • http://en.wikipedia.org/wiki/Basic_Multilingual_Plane
  • http://zh.wikipedia.org/wiki/Gb2312
  • http://zh.wikipedia.org/wiki/GBK
  • http://zh.wikipedia.org/wiki/GB18030
  • http://www.utf8.com/
  • http://www.unicode.org/versions/Unicode5.2.0
  • http://www.unicode.org/reports/tr18/
  • http://www.unicode.org/charts/
  • http://www.regular-expressions.info/charclass.html
  • http://wenq.org/index.cgi?ZenHei
  • http://wenq.org/index.cgi?MicroHei
  • http://wenq.org/?BitmapSong
  • http://vim.wikia.com/wiki/Perl_compatible_regular_expressions
  • http://perldoc.perl.org/perlunicode.html
  • http://msdn.microsoft.com/en-us/library/20bw873z.aspx
  • http://forum.ubuntu.org.cn/viewtopic.php?t=244756

源地址:http://blog.renren.com/GetEntry.do?id=768109271&owner=231526558

抱歉!评论已关闭.