10 文件编辑与查找

通过阅读本章,你将会了解到以下几项内容。

  • 字符集和字符编码
  • 编辑器简介
  • 文件查找

10.1 字符集和字符编码

参考网页:

提到文本文件,不得不说文件的字符集,对于英文世界,ASCII码足够他们玩耍的了,但是对于中文,我们还需要中文字符集,不然就会显示很多框框或者乱码等。

字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。中文文字数目大,而且还分为简体中文和繁体中文两种不同书写规则的文字,而计算机最初是按英语单字节字符设计的,因此,对中文字符进行编码,是中文信息交流的技术基础。

10.1.1 ASCII

ASCII(American Standard Code for Information Interchange,美国信息互换标准编码)是基于罗马字母表的一套电脑编码系统。

  • 特点 它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO 646。
  • 包含内容
    • 控制字符:回车键、退格、换行键等。
    • 可显示字符:英文大小写字符、阿拉伯数字和西文符号。
  • 技术特征 7位(bits)表示一个字符,共128字符,字符值从0到127,其中32到126是可打印字符。
  • 扩展字符集 7位编码的字符集只能支持128个字符,为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符,增加了表格符号、计算符号、希腊字母和特殊的拉丁符号。

10.1.2 GB2312

GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集·基本集》,由原中国国家标准总局发布,1981年5月1日实施,是中国国家标准的简体中文字符集。

它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。

包含内容

GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。其中包括6763个汉字,其中一级汉字3755个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

技术特征

(1)分区表示:

GB2312中对所收汉字进行了“ 分区” 处理,每区含有94个汉字/符号。这种表示方式也称为区位码。 各区包含的字符如下:01-09区为特殊符号;16-55区为一级汉字,按拼音排序;56-87区为二级汉字,按部首/笔画排序;10-15区及88-94区则未有编码。

(2)双字节表示

两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“ 高字节” ,而称第二字节为“ 低字节” 。 “ 高位字节” 使用了0xA1-0xF7(把01-87区的区号加上0xA0),“ 低位字节” 使用了0xA1-0xFE(把01-94加上0xA0)。

以GB2312字符集的第一个汉字“ 啊” 字为例,它的区号16,位号01,则区位码是1601,在大多数计算机程序中,高字节和低字节分别加0xA0得到程序的汉字处理编码0xB0A1。计算公式是:0xB0=0xA0+16, 0xA1=0xA0+1。

10.1.3 GBK字符集

GBK编码(Chinese Internal Code Specification)是中国大陆制订的、等同于UCS的新的中文编码扩展国家标准。gbk编码能够用来同时表示繁体字和简体字,而gb2312只 能表示简体字,gbk是兼容gb2312编码的。GBK工作小组于1995年10月,同年12月完成GBK规范。该编码标准兼容GB2312,共收录汉字 21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。Windows95/98简体中文版的字库表层编码就采用的是GBK,通过 GBK与UCS之间一一对应的码表与底层字库联系。

  • 英文名:Chinese Internal Code Specification
  • 中文名:汉字内码扩展规范1.0版
  • 双字节编码,GB2312-80的扩充,在码位上和GB2312-80兼容
  • 范围:8140~FEFE(剔除xx7F)共23940个码位。包含21003个汉字,包含了ISO/IEC 10646-1中的全部中日韩汉字。
  • 作用:它是GB2312的扩展,加入对繁体字的支持,兼容GB2312。
  • 位数:使用2个字节表示,可表示21886个字符。
  • 范围:高字节从81到FE,低字节从40到FE。

10.1.4 BIG5

大五码或五大码,1984年由台湾财团法人信息工业策进会和五家软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大众 (FIC)创立,故称大五码。

Big5码的产生,是因为当时台湾不同厂商各自推出不同的编码,如倚天码、IBM PS55、王安码等,彼此不能兼容;另一方面,台湾政府当时尚未推出官方的汉字编码,而中国大陆的GB2312编码亦未有收录繁体中文字。

Big5字符集共收录13,053个中文字,该字符集在中国台湾使用。耐人寻味的是该字符集重复地收录了两个相同的字:“ 兀” (0xA461及0xC94A)、“ 嗀” (0xDCD1及0xDDFC)。

编码方法

Big5码使用了双字节储存方法,以两个字节来编码一个字。第一个字节称为“ 高位字节” ,第二个字节称为“ 低位字节” 。高位字节的编码范围0xA1-0xF9,低位字节的编码范围0x40-0x7E及0xA1-0xFE。

各编码范围对应的字符类型如下:0xA140-0xA3BF为标点符号、希腊字母及特殊符号,另外于0xA259-0xA261,存放了双音节度量衡单位用字:兙兛兞兝兡兣嗧瓩糎;0xA440-0xC67E为常用汉字,先按笔划再按部首排序;0xC940-0xF9D5为次常用汉字,亦是先按笔划再按部首排序。

局限性

尽管Big5码内包含一万多个字符,但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字,没有包含日文平假名及片假名字母。

例如台湾视“ 着” 为“ 著” 的异体字,故没有收录“ 着” 字。康熙字典中的一些部首用字(如“ 亠” 、“ 疒” 、“ 辵” 、“ 癶” 等)、常见的人名用字(如“ 堃” 、“ 煊” 、“ 栢” 、“ 喆” 等) 也没有收录到Big5之中。

10.1.5 GB18030

GB18030的全称是GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,是我国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场上发布的软件必须符合本标准。

该标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位,收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容,填补Unicode扩展字符字汇“ 统一汉字扩展A” 的内容。并且与以前的国家字符编码标准(GB2312,GB13000.1)兼容。

编码方法

GB18030标准采用单字节、双字节和四字节三种方式对字符编码。单字节部分使用0×00至0×7F码(对应于ASCII码的相应码)。双字节部分,首字节码从0×81至0×FE,尾字节码位分别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE,第二、四个字节编码码位均为0×30至0×39。

包含内容

双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有关标点符号、表意文字描述符13个、增补的汉字和部首/构件80个、双字节编码的欧元符号等。四字节部分收录了上述双字节字符之外的,包括CJK统一汉字扩充A在内的GB 13000.1中的全部字符。

10.1.6 Unicode字符集

Unicode字符集(简称为UCS),国际标准组织于1984年4月成立ISO/IEC JTC1/SC2/WG2工作组,针对各国文字、符号进行统一性编码。1991年美国跨国公司成立Unicode Consortium,并于1991年10月与WG2达成协议,采用同一编码字集。目前Unicode是采用16位编码体系,其字符集内容与 ISO10646的BMP(Basic Multilingual Plane)相同。Unicode于1992年6月通过DIS(Draf International Standard),目前版本V2.0于1996公布,内容包含符号6811个,汉字20902个,韩文拼音11172个,造字区6400个,保留 20249个,共计65534个。Unicode编码后的大小是一样的.例如一个英文字母 “a” 和 一个汉字 “好”,编码后都是占用的空间大小是一样的,都是两个字节!

Unicode可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容iso8859-1编码的, 也不兼容任何编码。不过,相对于iso8859-1编码来说,uniocode编码只是在前面增加了一个0字节,比如字母’a’为“00 61”。

需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode编码来处理的,比如java。

UNICODE字符集有多个编码方式,分别是UTF-8,UTF-16,UTF-32和UTF-7编码。

10.1.6.1 UTF-8

UTF:UCS Transformation Format.考虑到unicode编码不兼容iso8859-1编码,而且容易占用更多的空间:因为对于英文字母,unicode也需要两个字节来表 示。所以unicode不便于传输和存储。因此而产生了utf编码,utf编码兼容iso8859-1编码,同时也可以用来表示所有语言的字符,不 过,utf编码是不定长编码,每一个字符的长度从1-6个字节不等。另外,utf编码自带简单的校验功能。一般来讲,英文字母都是用一个字节表示,而汉字 使用三个字节。

注意,虽然说utf是为了使用更少的空间而使用的,但那只是相对于unicode编码来说,如果已经知道是汉字,则使用GB2312/GBK无疑是 最节省的。不过另一方面,值得说明的是,虽然utf编码对汉字使用3个字节,但即使对于汉字网页,utf编码也会比unicode编码节省,因为网页中包 含了很多的英文字符。

UTF8编码后的大小是不一定,例如一个英文字母a和一个汉字,编码后占用的空间大小就不样了,前者是一个字节,后者是三个字节!编码的方法是从低位到高位。黄色为标志位其它着色为了显示其,编码后的位置。

10.1.6.2 UTF-16

采用2 字节,Unicode中不同部分的字符都同样基于现有的标准。这是为了便于转换。从 0x0000到0x007F是ASCII字符,从0x0080到0x00FF是ISO-8859-1对ASCII的扩展。希腊字母表使用从0x0370到 0x03FF 的代码,斯拉夫语使用从0x0400到0x04FF的代码,美国使用从0x0530到0x058F的代码,希伯来语使用从0x0590到0x05FF的代 码。中国、日本和韩国的象形文字(总称为CJK)占用了从0x3000到0x9FFF的代码;

由于0x00在c语言及操作系统文件名等中有特殊意义,故很多情况下需要UTF-8编码保存文本,去掉这个0x00。举例如下:

  • UTF-16: 0x0080 = 0000 0000 1000 0000
  • UTF-8: 0xC280 = 1100 0010 1000 0000

10.1.6.3 UTF-32

采用4字节。

10.1.6.4 UTF-7

A Mail-Safe Transformation Format of Unicode(RFC1642)。这是一种使用 7 位 ASCII 码对 Unicode 码进行转换的编码。它的设计目的仍然是为了在只能传递 7 为编码的邮件网关中传递信息。 UTF-7 对英语字母、数字和常见符号直接显示,而对其他符号用修正的 Base64 编码。符号 + 和 - 号控制编码过程的开始和暂停。所以乱码中如果夹有英文单词,并且相伴有 + 号和 - 号,这就有可能是 UTF-7 编码。

  • 作用:为世界650种语言进行统一编码,兼容ISO-8859-1。
  • 位数:UNICODE字符集有多个编码方式,分别是UTF-8,UTF-16和UTF-32。

10.1.7 编码的常用命令

在 Linux 下通常使用 UTF-8 编码。如果你需要对用户姓名排序的话,建议使用 GB18030 编码,以便直接排序。各种编码也是可以相互转换的。

如果我们想查看某个文件的编码方式,可以使用file -i命令。

$ file -i test.md
test.md: text/plain; charset=utf-8

这样就可以看到test.md文件的属性普通文本文件text/plain以及编码方式为UTF-8,charset=utf-8

一般的编辑器都是支持编码方式转换的,如果你想改变某个文件的编码方式,可以使用iconv工具。 iconv 工具的使用方法如下:

$ iconv option
$ iconv options -f from-encoding -t to-encoding inputfile(s) -o outputfile 

在这里,-f--from-code 表明了输入编码,而 -t--to-encoding 指定了输出编码。

为了列出所有已有编码的字符集,你可以使用以下命令:

$ iconv -l
以下的列表包含所有已知的编码字符集,但这不代表所有的字符名称组合皆可用于
命令行的 "来源" 以及 "目的" 参数。一个编码字符集可以用几个不同的名称
来表示 ("别名")

  437, 500, 500V1, 850, 851, 852, 855, 856, 857, 858, 860, 861, 862, 863, 864,
  865, 866, 866NAV, 869, 874, 904, 1026, 1046, 1047, 8859_1, 8859_2, 8859_3,
  8859_4, 8859_5, 8859_6, 8859_7, 8859_8, 8859_9, 10646-1:1993,
  10646-1:1993/UCS4, ANSI_X3.4-1968, ANSI_X3.4-1986, ANSI_X3.4,

下面举个小例子。其中test.md文件是包含中英文的。

在运行 iconv 命令之后,我们可以像下面这样检查输出文件的内容,和它使用的字符编码。

$ file -i test.md
test.md: text/plain; charset=utf-8
$ cat test.md 
: Shell 提示符中用到的转义字符
$ iconv -f utf-8 -t GB18030 test.md -o out.md
$ cat out.md
: Shell ��ʾ�����õ���ת���ַ�
$ file -i out.md
out.md: text/plain; charset=iso-8859-1

你会发现转换后,电脑没有正确识别出out.md文件的编码,如果你使用文本编辑器gedit打开out.md文件,还是可以正常打开的。