一
GB2312与cp936
1. GB2312
简介
GB2312
即
GB2312-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 pages
在
80
到
90
年代的
Windows
操作系统中使用,当
Windows
实现了
Unicode
时,
code pages
就逐渐被取代。
Code Page
这个词来源于
IBM
的基于
EBCDIC
的
mainframe
系统,但包括微软、
SAP
和
Oracle
在内的很多制造商都使用这个说法。
另一个很奇怪的事情是,同样一份以
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+00A4
到
U+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
(也就是不含
80
和
FF
),第二字节的一部分领域在
40-FE
,其他领域在
80-FE
。
三 GB18030
1.
简介
最新版本为
GB 18030-2005
,与
GB 2312-1980
完全兼容,与
GBK
基本兼容,支持
GB 13000
及
Unicode
的全部统一汉字,共收录汉字
70244
个。与
UTF-8
相同,采用多字节编码,每个字可以由
1
个、
2
个或
4
个字节组成。支持中国国内少数民族的文字,收录范围包含繁体汉字以及日韩汉字。
2.
编码
单字节部分,收录了
GB/T 11383-1989
的
0x00
到
0x7F
全部
128
个字符;双字节部分:
GB 13000.1-1993
的全部
CJK
统一汉字字符等,其首字节码位从
0x81
至
0xFE
,尾字节码位分别是
0x40
至
0x7E
和
0x80
至
0xFE
。;四字节部分:收录了上述双字节字符之外的,
GB 13000
的
CJK
统一汉字扩充
A
、
CJK
统一汉字扩充
B
和已经在
GB 13000
中编码的中国少数民族文字的字符,采用
0x30
至
0x39
作为对双字节编码的扩充的后缀。这样扩充的四字节编码,其范围为
0x81308130
到
0xFE39FE39
。四字节字符的第一个字节的编码为
0x81
至
0xFE
;第二个字节的编码范围为
0x30
至
0x39
;第三个字节编码范围为
0x81
至
0xFE
;第四个字节编码范围为
0x30
至
0x39
。
四 Unicode
1. Unicode
中的
scripts
Unicode
中的
script
指的是一种或多种书写系统中,用来代表文字信息的一个字符或其他书写符号的集合。例如,俄语和乌克兰语分别是西里尔
script
的不同子集。有些
script
支持且仅支持一种书写系统和语言,如亚美尼亚
script
;另一些
scripts
支持多种不同的书写系统,如
Latin script
支持英语、法语、德语、意大利语、越南语和拉丁语。有些语言使用多种不同的书写系统,因此也使用若干个
scripts
。在土耳其语中,阿拉伯语的
script
在
20
世纪之前使用,但到
20
世纪早期则转变为
Latin script
。汉字书写系统使用在以下语言中:普通话、吴语、粤语、闽语(译者注:台语)、湘语、客家语、赣语、晋语、徽州语、广西平语、侗语、白语(已废弃)、苗语(已废弃)、壮语(已废弃)、日语、韩语(已废弃,只使用于学术文本和报纸中),越南语(用于历史文献、学术文献或出于艺术与审美的考虑)及其他已经失传的语言(契丹文、女真文、西夏文)。
与
scripts
相补充的是
Unicode symbols
。
Scripts
和
symbols
覆盖了所有的
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统一表意文字扩展A(3400-4DBF):罕用汉字
- CJK统一表意文字扩展B(20000-2A6DF):罕用汉字
- CJK统一表意文字扩展C(2A700-2B73F):罕用汉字
- CJK兼容表意文字(F900-FAFF):重复字符,可统一的异形字
- CJK兼容表意文字补充(2F800-2FA1F):可统一的异形字
五 UTF-8
1.
简介
全称
UCS Transformation Format �C 8-bit
,是一种对
Unicode
的多字节编码。与
UTF-16
和
UTF-32
类似,
UTF-8
可以表示
Unicode
字符集中的每个字符。与它们不同的是,
UTF-8
与
ASCII
是向后兼容的,并且避免了尾数(
endianness
)的复杂性。鉴于各种原因,
UTF-8
已成为
www
最重要的字符编码,涉及超过半数网页。
UTF-8
使用
1
至
4
个字节对
Unicode
字符集中的
1,112,064
个代码点中的每一个进行编码。具体而言,使用
1-3
个不等的字节数编码
Unicode
的第
0
个平面。数值较低的代码点使用较少的字节数,使得编码体系较为高效。注意,
Unicode
对所有字符进行编码,完成从字符到代码点(如
0x4E00
)的映射,而与字符的具体表示无关;
UTF-8
完成由编码到内在表示(字节码)的映射,而不关心某个编码具体代表哪个字符。
2.
编码范围
Unicode
字符集的前
128
个字符与
ASCII
码保持
一对一关系,使用一个字节进行编码,使得有效的
ASCII
文本在
UTF-8
编码的
Unicode
下仍然有效。理论上,
UTF-8
可以至多编码
2
的
31
次方个字符(即
Universal
字符集起草时的理论上限)。
3.
编码规则
如果一个字符用一个字节编码,则最高位是
0
,其他位给出编码值(
0
到
127
);
如果一个字符用
k
(
k>=2
)个字节编码,则第一个字节的前
k
位为
1
,接着是一个
0
。随后的(
k-1
)个字节全部由“
10
”开头。所有字节的剩余位连接起来,形成了
Unicode
代码点值,从
0x80
到
0x10FFFF
。由此可见:
(
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
)汉字“一”是
Unicode
中
CJK
统一表意文字区的第一个字符,
Unicode
码为
0x4e00
,既然表示为三个字节,则使用“
1110xxxx 10xxxxxx 10xxxxxx
”的模板,把
4e00
这十六位编码套进去,正好就是“
e4 b8 80
”;
(
3
)
fileformat
是
unix
,因此换行符是一个
<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
等宽字体,并内置
Hinting
和
Kerning
信息。微米黑字体文件极小,特别使用于便携式电脑设备。
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+C0B5
的
Unicode
字符”,而没说具体需要比较哪些字节,因为具体的字节是由代表这个
Unicode
代码点的编码方式在内部决定的。如果程序内部使用的是
UTF-8
编码,这个字符就用
3
个字符表示。不过使用支持
Unicode
程序的用户,并不需要关心这个。
为了匹配任何一个
Unicode
字符,应该用
\X
,这相当于
Unicode
中的点号。在
Java
中,用
\uFFFF
(
FFFF
是代码点)来匹配某个特定的
Unicode
字符。
2. Perl
或
PCRE
中
Unicode
字符的正则表达式表示
在
Perl
或
PCRE
中,并不支持
\uFFFF
这样的语法,而是使用
\x{FFFF}
。例如,
\x{1234}
不会和“匹配
\x 1234
次”混淆,而是永远代表
U+1234
这个
Unicode
字符;
\x{1234}{5678}
则代表匹配
U+1234
这个
Unicode
字符整整
5678
次。
Perl
或
PCRE
还是极少数的支持基于
Scripts
对
Unicode
进行匹配的正则表达式引擎!方法是
\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. Vim
对
Unicode
正则表达式的支持
作为最强大的文本编辑器,
Vim
对正则表达式的支持是人尽皆知的。而且,毕竟是文本编辑器,执行个查找啊替换啊这种处理会比用
perl
直观得多。但是,对于
Unicode
字符的支持,
Vim
采用的正则表达式引擎却远比不上
Perl(图为节选)
:
有人说,为什么
Vim
不用
PCRE
呢?回复说,
Vi
比
Perl
出来的早得多,应该问为什么
Perl
不跟
Vi
学。无论如何,在
Vim
里匹配
Unicode
字符会遇到一点麻烦:你可以用
/\u4e00
匹配“一”,也可以用
/[\u4e00-\u4eff]
匹配
Unicode
表中的第一行汉字(一、丁、万、三、上……),却不能用
/[\u4e00-\u9fff]
匹配
CJK
统一表意文字区块中的所有文字!不知道是不是我的使用有问题!
八 Ubuntu中的字符映射表(Character Map)
这是
Ubuntu
中相当于
Windows
“字符映射表”的软件,可以在
Applications -> Accessories
中找到。且不说以文泉驿微米黑显示的字符表有多好看,就说这个
Character Details
就做得非常帅,给出的信息包括:
UTF-8
编码方式、
XML
实体表示形式、英文释义、普通话发音、广东话发音、日语发音、韩语发音!
工作过程中有时候需要看看
Unicode
的
Scripts
,或者查找某个字符的
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