UTF-8 and Unicode FAQ for Unix/Linux

作者 Markus Kuhn 

原文地址:http: //www.cl.cam.ac.uk/~mgk25/unicode.html

译者:Love.Katherine ,2007-8-30

译文地址:http://blog.csdn.net/lovekatherine/archive/2007/08/30/1765903.aspx


转载时务必以超链接形式标明文章原始出处及作者、译者信息。

 

    本 文对在 POSIX 系统 (Linux,Unix) 中如何应用 Unicode/UTF-8 这一话题进行了全面讲解,不 仅为普通用户提供介绍性信息,也为富有经验的开发者提供详尽的参考。

    Unicode 已经开始在各个层面上取代 ASCII ISO 8859 以及 EUC 。它不仅允许用户处理地球上的任何文字和语言,而且还支持一套范围广 泛的数学和技术符号集,以用于简化科学信息的交流。

    通 过使用 UTF-8 这种编码方式,原 本完全围绕 ASCII 设计的环境,例如 Unix ,也可以方便且向后兼容的 应用 Unicode UTF-8 就是 Unix Linux 以及类似系统中 Unicode 应用形式。现在是时候该对它进行深入了解,并保证你的软件对 UTF-8 编码方式提供良好支持。

目录


什 么是 UCS ISO 10646?

国 际标准 ISO 10646 定义了 用字符集 (UCS ) UCS 是其它所有现有字符集标准的超集,它保证与其它字符集之间 的 双向兼容性。这意味着如果你将任意字符串转换为 UCS 格式再转换为源格式,不会出现信息的丢失。

UCS
中包含了用于表示 所有已知语言的字符。这不仅包括拉丁语、希腊语、斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语和格鲁吉亚语,还包括中文、日文和韩文这 样 的表意文字,以及平假名、片假名、 Hangul、 梵文 孟加拉语 果鲁穆奇语、 古吉拉特语 奥里雅语 泰米尔语、 泰卢固语、 埃纳德语 马拉雅拉姆语 泰国语、 老挝语、 高棉 ,、 汉语拼音、 藏语、 Runic( 古代北欧文字 )、 埃塞俄比亚语 、 Canadian Syllabics、 切罗基语、 蒙古语、 欧甘语 缅甸语 僧伽罗 、Thaana、 彝语和其它语言。对于上面未提及的语言,对其如何编码的研究正在进行 中,并最终都会被加入 UCS 。这其中不仅包括古语言如 楔性文字 埃及象形文字 以及各种印欧语系语言,甚至还包括挑选出的艺术语言如托儿金 [ 指环王的作者 ] 创造的 Tengwar Cirth. UCS 中 还包含大量的图形、印刷、数学以及科学符号,包括所有由 Tex Postscript  APL 、国际音标字母表 (IPA) MS-DOC MS-Windows Macintosh OCR 字体、以及很多字处理和出版系统提供的符号。该标准 (ISO 10646) 还处在不断的维护和更新之中,未来的很多年内,会有更多的外来的和专 用符号、字符被加入到 UCS 之中。

ISO 10646
原本 被定义了一个 31-bit 的字符集。元素个数为 216 ,且元素 ( 32-bit 的整型数值表示 ) 之间只有低 16 位不同的元素子集,被定义为 UCS 的一个平面。

最常用的字符,包括各主要旧有编 码标准中的所有字符,全部被放入了 UCS 的第一个平面中 ( 值域为 0x0000 0xFFFD) ,该平面 又 被称为基本多语言平面 (BMP ) 或平面 0 。位于 BMP 之外的字符大多数都是用于特殊应用,例如古代文字和科学符号。按照目 前的计划,永远不会有字符被分配到定义为从 0x000000 0x10FFFF 、可容纳超过 100 万个潜在未来字符的 21-bit 编码空间之外。 ISO 16046-1 标准最初于 1993 被公布,它定义了 UCS 这个字符集的结构以及 BMP 的内容。 2001 又增加了 ISO 10646-2 标准,定义了 BMP 意外的字符编码。 2003 年,这两部分被合并为单一的 ISO 10646 标准。新的字符仍然被不断的添加进入 UCS ,但是已有的字符会保持稳定,不会发生变化了。

UCS 为每个字符不仅分配了码值,还有一个正式名称。一个表示 UCS Unicode 码值的 16 进制数通常在表示时加上前缀 "U+", 例如 U+0041 表示拉丁大写子母 A UCS 码值。码值在 U+0000 U+007F 之间的 UCS 字符与 US-ASCII(ISO 646 IRV) 相同,码值在 U+0000 U+00FF 之间的字符与 ISO 8859-1(Latin-1) 相同。码值在 U+E000 U+F8FF 之间,以及 BMP 之外的 UCS 字符是被保留的、留作私用的。 UCS 还定义了将 UCS 字符串编码为字节串的几种方法,例如 UTF-8 UTF-16

UCS 标准的完整引用形式为:

International Standard ISO/IEC 10646, Information technology — Universal Multiple-Octet Coded Character Set (UCS) . Third edition, International Organization for Standardization, Geneva, 2003.  

可从 ISO 线订购 该标准的文档格式为 PDF 的光盘,价格为 112 瑞士法郎。

[ 更新 ] 2006 9 月, ISO 在它的 免费标准页面 公布了 ISO 16046:2003 的在线免费 PDF 文档,该 ZIP文件 大小为 82 MB

什 么是组合字符 ?

UCS 中的一些码值被分配给了组合字符。 它 们类似于打字机上的不占空位的重音键。组合字符自身不是一个完整的字 符。它是一个重音或其它 指示 标记,用于添加到之前的字符之上。这样,就可以为任何字符添加重音。 那些最重要的加重音的字符,就像普通语言的正字法 (orthographies of common languages) 中 用到的那样,在 UCS 中有自己独立的位置,来保证其与旧字符集的向后兼容性。这些字符被称 为 制 字符 UCS 提供预制字符是为了与那些未定义组合字符的旧编码集,例如 ISO 8859 ,保持向后兼容性。组合字符机制允许用户为任何字符添加重音或其它 指示标记。这对于科学标记尤其重要,例如数学方程式以及国际音标字母表,可能 会需要在一个基本字符后 组合上一个或多个指示标记

组合字符位于其要修饰的 字符之后。例如,德语中的元音变音字符 Ä( 带分音符的拉丁字母 A) ,可以用码值为 U+00C4 UCS 预制字符 来 表示,也可以通过普通拉丁字母 A 后跟组合分音子符的组合 U+0041 U+0308 来表示。当需要堆叠多个重音符 或在一个基本字符的上面和下面都要加上组合标记时 , 可以使用多个组合字符 比如在泰国文中 , 一个基本字符最多可加上两个组合字符。

 

什么是UCS实现级别?

无 法指望所有系统都支持 UCS 中的全部高级机制,例如组合字符。因此, ISO 10646 定义了以下三种实现级别 :                                                                                           

级 别 1

    不支持组合字符和Hangul Jamo字符

级 别

        类似于级别 1, 但是对于某些语言 , 允许一个固定列表中的组合字符 ( 例如 , 希伯来语 , 阿拉伯语 , 梵文 , 孟加拉语 , 果鲁穆奇语 古吉拉特语 奥里雅语 泰 米尔语 泰卢固语 , 埃纳德语 , 马拉雅拉姆语 泰国语 , 老挝语 )
      
如果具体实现中没有对最 起码的几个组合字符的支持,   就无法使用 UCS 完整地表达这些语言。

级 别 3

        支持所有UCS字符;举例来说,这样数学家就可以对任意字符加一个波浪或一个箭头或是两者兼有。

USC 是否被采纳为国家标准 ?

是的,很多国家已经采纳 ISO 10646 作为国家标准,某些情况下在原有标准基础上添加了对旧国家标准的交叉 引用,实现指引以及定义各种实现子集。

  • 中国 : GB 13000.1-93
  • 日本 : JIS X 0221-1:2001
  • 韩国 : KS X 1005-1:1995 ( 包含 ISO 10646-1:1993 的修正案 1-7)
  • 越南 : TCVN 6909:2001
  • 伊朗 : ISIRI 6219:2002

什 么是 Unicode?

上 世纪 80 年代后期,两个尝试创立统一字符集的项目同时独立存在。一个是 际标准化组织 (ISO) ISO 10646 项目 , 另 一个是由多语言软件制造商协会 ( 最初成员大多数是美国公司 ) 组织的 Unicode 项目 幸运的是,两个项目的参 与者在大约 1991 年意识到,世界并不需要两个不同的统一字符集。他们将双方的工作进行 合并,并为创立一个统一编码表而共同工作。 两个项目如今仍然存在,并独立公布各自的标准,然而 Unicode 协会和 ISO/IEC JTC1/SC2 同意保持 Unicode ISO 10646 的编码表的相互兼容,并为任何的未来扩展进行紧密协调。 Unicode 1.1 ISO 10646-1:1993 相对应, Unicode 3.0 ISO 10646-1:2000 相对应, Unicode 3.2 中添加了 ISO 10646-2:2001,Unicode 4.0 对应于 ISO 10646:2003,Unicode 5.0 对应于 ISO 10646:2003 加上其修正案 1-3 。所有 2.0 版本 之后的 Unicode 是向后兼容的,只有新的字符会被加入,已有的字符在未来不会被删 除或是改 变。

Unicode
标准 可以像任何普通书籍一般被订购,例如通过 amazon.com 价格在 60 USD 左右。

The Unicode Consortium: The Unicode Standard 5.0 ,
Addison-Wesley, 2006,
ISBN 0-321-48091-0.

如果你的工作频繁的与字处理和字 符集打交道,你绝对应该拥有一份 Unicode 标准。 Unicode 5.0 还可以 在线获取

Unicode ISO 10646 之间的区别是什么 ?

Unicode 协会公布的 Unicode 标准 对应于实现级别 3 ISO 10646 。两个标准中所有字符都有相同的位置并有相同的名字。

Unicode 标准额外为某些字符定义了更多的语义。一般来说对于高质量印刷出版系 统的实现者而言是更好的参考。 Unicode 详细说 明 了某些文字 ( 如阿拉伯语 ) 的表示形式的绘制算法,处理双向文本 ( 如拉丁语和希伯来语的混合使用 ) 的算法,排序和字符串比较所使用的算法以及其它更多内容。

另一方面, ISO 10646 标准,就像旧有的 ISO 8859(Latin-1) 标准一样,不过是一个简单的字符集表。它指定了与标准相关的一些术 语,定义了一些编码方法,并详细说明了如何实现 UCS 与其 它已有的 ISO 标准的结合使用 , 例如 ISO 6429 ISO 2022 。还存在其它紧密相关的 ISO 标准,例如关于 UCS 字符串排序的 ISO 14651 ISO 10646-1 标准的一个优点是,它以五种不同风格的变种来提供 CJK 示例字型,而 Unicode 标准只以一种汉字风格来显式 CJK 表意文字。

什 么是 UTF-8?

UCS Unicode 本质上只是将整型数值分配给字符的码表。而如何将一系列这样的字符或 是单个字符的整型数值用字节串表示,则存在几种 不同的方法。 最 显然的两种存储 Unicode 文本的编码方法是 2 4 字 节序列组成的序列。这两种编码方法的正式名字分别是 UCS-2 UCS-4 。除非另外指定,每个 字 符对应的字节串遵循大端字节序 (Big-endian) 。一个 ASCI Latin-1 文件只需要在每个 ASCII 字节前插入一个 0X00 字节,就可以 转 换为 UCS-2 文件;如果想转换为 UCS-4 文件,则需要在每个 ASCII 字节前插入三个 0x00 字节。

Unix 世界中使用 UCS-2( UCS-4) 会导致非常严重的问题。使用这两种编码方式的字符串,可能会包含诸如 字节 "/0" "/" 为很多宽字符的组成部 分,而这样的字节在文件名和其它 C 语言库函数中有特殊的意义。此外,大多数 Unix 工具都被设计用来处理 ASCII 文件的,不进行大 幅 度的修改是无法读取 16-bit 字符的。基于这些原因,在文件名、文本文件、环境变量等地方, UCS-2 ( UCS-4 ) 不是一种合适的 Unicode 外部编码。

ISO 10646-1:2000 D RFC3629 Unicode 4.0 标准的 3.9 节中均有定义的 UTF-8 编码方法不存在上述问题。它很显然是在类 Unix 风格的操作系统中使用 Unicode 合适方法。

UTF-8 具有以下特性:

  • 码值在 U+0000 U+007F 之间的 UCS 字符被简单的编码为 0X00 0X7F( 兼容 ASCII) 。这意味着只包含 7- bit ASCII 字符的文件,在 ASCII UTF-8 两种编码方法下具有相同的编码。
  • 所有码值大于 U+007 UCS 字符都被编码为若干个字节组成的序列,序列中每个字节最高位均为 1 。因此, ASCII 字节 (0X00-0X7F) 不可能作为任何其它字符的一部分而出现。
  • 表示一个非 ASCII 字符的多字节序列中的第一个字节总是位于 0XC0 0XFD 之间,它能指出该字符由几个字节表示。多字节序 列 中的所有后续字节都位于 0X80 0XBF 。这使得重新同步变得容易,编码变得无状态化,对于字节的丢失具备健 壮性。
  • 所有可能的 231 UCS 字符都可被编码。
  • UTF-8 编码的字符理论上最长可达 6 字节长,不过 16-bit BMP 字符最多为 3 字节长。
  • 保留了大端 UCS-4 字节串的排序顺序。
  • 字节 0XFE 0XFF UTF-8 编码中永远不会被用到。

以下字节序列用于表示一个字符。 要使用的字节序列由字符的 Unicode 码值决定。

 

U-00000000 – U-0000007F:

0xxxxxxx

U-00000080 – U-000007FF:

110xxxxx 10xxxxxx

U-00000800 – U-0000FFFF:

1110xxxx 10xxxxxx 10xxxxxx

U-00010000 – U-001FFFFF:

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

U-00200000 – U-03FFFFFF:

111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

U-04000000 – U-7FFFFFFF:

1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


以上的比特位 xxx UCS 字符码值的二进制表示进行填充,最右边的 x 比特的权值最低。能表示同一字符码值的若干多字节序列中,只有最短的 那个可以在编码 时被使用。注意,在多字节序列中,第一个字节中开头 '1' 的数目就等于整个字节序列中的字节数。

例子 :  Unicode 字符 U+00A9=10101011( 版权符号 ) UTF-8 方法中被编码为

11000010   10101001=0XC2   0XA9

而字符 U+2260 0010 0010 0110 0000( 不等于号 ) 被编码为

11100010   10001001   10100000 0XE2   0X89   0XA0

这种编码方法的正式名字和拼写是 UTF-8 ,这里 UTF 代表 U CS T ransformation F ormat 。请勿在任何文档中用任何其它方式 ( utf8 UTF_8) 来表示 UTF-8 ,当然除非你是指称一个变量名而不是这种编码本身。

针对 UTF-8 解码函数开发者的重要说明 基于安全的原因, UTF-8 的解码函数不允许接受超出必要编码长度的 UTF-8 字节序列。例如,字符 U+000A( 换行符 ) 只允许从 UTF-8 字节流中以 0X0A 的形式被接受 ( 解码 ) , 而不是以下五种过长形式的任何一种:

0XC0 0X8A

0XE0 0X80 0X8A

0XF0 0X80 0X80 0X8A

0XF8 0X80 0X80 0X80 0X8A

0XFC 0X80 0X80 0X80 0X80 0X8A

任何过长 UTF-8 序列都可能被滥用,以绕过 UTF-8 的子串测试 —— 它只搜索最短的可能编 码。 所有过长 UTF-8 字节序列都以以下一种字节模式作为起始:

1100000x (10xxxxxx )

11100000 100xxxxx (10xxxxxx )

11110000 1000xxxx (10xxxxxx 10xxxxxx )

11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx )

11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx )


此外还要注意,
UCS 码值 U+D800 U+DFFF(UTF-16 代理 ) 以 及 U+FFFE U+FFFF 不允许出现在正常的 UTF- 8 UCS-4 编码的数据中。基于安全原因, UTF-8 解码器应将它们视为畸形或过长序列。

Markus Kuhn UTF -8解码器压力测试文件 中含有畸形或过长序列的系统性集合,可以用来帮助检验解码器的健壮 性。

 

谁发明的UTF-8?

 

如 今被称为 UTF-8 的编码方式是由 Ken Thompson 发明的。它于 1992-09-02 晚间在新泽西的一家餐馆里诞生; Ken Thompson Rob Pike 场 的情况下在餐具垫上完成了 UTF-8 的设计 ( 参见 Rob Pike UTF -8的历史 ”) 1992 8 月, Gary Miller (IBM), Greger Leijonhufvud and John Entenmann (SMI) 曾 在 X/Open 的工作文档中提出设计一种 FSS/UTF( 文件系统安全的 UCS 转换格式 ) ,以替代 ISO 10646-1 第一版中的除法密集型的 UTF-1 编码方法; Thompson 的工作成果取代了这一更早的尝试。 1992 9 月 的第一个星期结束之前, Pike Thompson 己 将 AT&T 贝尔实验室的 Plan 9 转变成世界上第一个使用 UTF-8 的操作系统。他们在 USENIX 1993 冬天的技术大会上报告了他们的经验 (USENIX Winter 1993 Technical Conference , San Diego, January 25-29, 1993, Proceedings, pp. 43-50) FSS/UTF 也曾被暂时命名为 UTF-2 ,之后被更名为 UTF-8 ,并由 XOJIG(X/Open Joint Internationalization Group) 完成了标准化过程。

 

哪里可以找到优质的UTF-8示例文件?

 

以下是一些有趣的用于测试和示范 的 UTF-8 示例文件:

存 在哪些不同的编码方法 ?

UCS Unicode 标准两者本质上都是为每个字符分配对应码值的很大的表格。在使用 "UCS","ISO 16046" "Unicode" 这些术语时,所表示的只是字符和码值之间的映射关系,而并未涉及以何 种方式将这些码值存储为字节串。

ISO 10646-1 中定义了 UCS-2 UCS-4 两种编码方法。它们分别是一个字符对应 2 字节和 4 字节。 ISO 10646 从最初就被设计成一个 31-bit 的字符集 ( 码值在 U+00000000 U+7FFFFFFF 之间 ) , 然而直到 2001 才出现第一个不在 BMP( 即码表的前 216 个位置,参见 ISO 10646-2 Unicode 3.1 ) 之 中的字符。 UCS-4 可以表示全部可能的 UCS Unicode 字符,而 UCS-2 只能表示位于 BMP 之中的字符 (U+ 0000 U+FFFF)

“Unicode” 原本暗示着会采用 UCS-2 编码方法,并且最初在码表中并未为 BMP 之外的字符预留位置。然 而, 事实表明,为 了支持某些特殊应用 ( 古代文字,象形文字,数学和音乐排版等 ) ,必需的字符数超出了 64K 的容量。因此, Unicode 被转变为一种 21-bit 的字符 集, 支持的码值范围为从 U+00000000 U+0010FFFF BMP 为此定义了 2 x 1024 个特殊字符 (U+D800 U+DFFF) ,称为代理字符 (surrogate character); 把两个 16-bit 的代理字符连用,可以用来表示 1024 x 1024 non-BMP 字符。这样就产生了 UTF-16 它向后兼容 UCS-2 ,并能用于扩展后 21-bit Unicode 的编码。 UTF-32 Unicode 标准中提出的用于表示 21-bit Unicode 4 字 节编码方式。 UTF-32 UCS-4 两种编码方法其实是相同的,唯一的区别在于 UTF-32 从不会用于表示码值大于 U+ 0010FFFF 字符,而 UCS-4 可用于表示不超过 U+7FFFFFFF 231 个字符。 ISO 10646 工作小组已承诺保证不会为任何字符分配超过 U+00107FFF 的码值,保证 UCS-4 UTF-32 这两种编码方法在实际应用中完全相同。

除此之外, UTF-8 被引入用来提供一 种 向后兼容 ASCII 的编码方法。 UCS Unicode 标准中对 UTF-8 的定义稍有不同,因为在 UCS 中, UTF-8 字节序列的最大可能长度为 6 ,以表示所有码值不大于 U+7FFFFFFF 字符 ; 而在 Unicode 中, UTF-8 字节序列的最大可能长度为 4 ,以表示所有码值不大于 U+0010FFFF 的字符。 ( 这一差别在本质上与 UCS-4 UTF-32 之间的相同 )

编码名 UCS-2,UCS-4,UTF-16,UTF-32 并未表明所采取的字节序,然而根据 ISO 10646-1 标准,除非另有约定,大端字节序为首选。在编码后面附加 "BE"( 大端,高位在前 ) "LE"( 小端,低位在前 ) 来显示指定字节序,这已经 成 为惯例。


为了能实现自动检测字节 序,在某些平台 ( 特别是 Win32) 上,每个 Unicode 文件都以字符 U+FEFF( 零宽度空白符 ) 作为起始,已经成了一种惯 例; 该字符又被称为字节序标记 ( Byte-Order Mark (BOM) ) 。该字符的字节对换对等体 U+FFFE 是一个非法 ( 未分配 ) Unicode 字符,因此它可以用来无二义性的区分 UTF-16 UTF-32 的大端和小 端 变种。

一个功能完备的编码转换器必须提 供以下 13 Unicode UCS 编码变种:

UCS-2, UCS-2BE, UCS-2LE, UCS-4, UCS-4LE, UCS-4BE, UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, UTF-32LE

若未显式指明字节序,则采用执行 转换操作的 CPU 的字节序,并在从输入流中每次读进字符 U+FFFE 时就改变当前字节序。 USC-4 UTF-32 ,以及 UCS-2 UTF-16 的编码输出的区别在于越界字符的处理。处理不可表示字符的应急机制必 须分别在 UTF-32( 码值大于 U+0010FFFF) UCS-2( 码值大于 U+FFFF) 中被激活;而这些码值在 USC-4 UTF-16 中则会提供相应的表示。

UTF-1 , UTF-7 , SCSU 及很多其它各具特性的 UCS 编码方法现在只剩下历史意义罢了,它们从未被广泛应用过,应该避免使 用这些编码方法。

一个优秀的编码转换器还应该提供 选择性添加或移除 BOM 的特性:

  • 无条件的为输出添加 U+FEFF 前缀
  • 为输出添加 U+FEFF 前缀,除非该前缀已经存在
  • 如果输出第一个字符为 U+FEFF, 则移除该字符

对于 UTF-8 ,同样存在使用 UTF-8 编码后的 BOM( 字节串 :0XFF 0XBB 0XBF) 作为 UTF-8 文件起始标志的建议。然而基于以下原因,绝不应该在 POSIX 系统中采用这种做法:

  • POSIX 系统中,应该通过 locale 信息而不是文 件类型魔数来 确认纯文本文件的编码方法。混淆这两个概念会增加复杂性,并 破 坏已有功能。
  • 在文件头部添加 UTF-8 签名会对很多已有惯例产生妨碍,例如内核在一个纯文本的可执行文件的 起始处查找 "#!" ,以定位合适的 解 释器。
  • BOM 的正确处理会为简单程序增加不必要的复杂性,例如 cat grep 这样将多个文件的内容进行合并的程序。

除了规定可选的编码方法外, Unicode 还规定了各种 范式 提供合理的 Unicode 子集,尤其是为了消除预制字符和组合字符的存在所导致的编码二义性。

  • Normalization Form D (NFD): 尽可能的将所有预制字符分裂成 字 符序列,例如使用 U+0041 U+0308( 大写拉丁 字母 A, 组合分音符号   ̈ ) 不是 U+00C4( Ä ) 此外,避免使用 已废弃的字符;例如,使用 U+0041 U+030A( 大写拉丁字母 A, 组合符号   ̊ ) 而不是使用 U+212B( 物理符号 : )。
  • Normalization Form C (NFC):   尽可能的 使 用预制字符而不是字符序列。例如是用 U+00C4( Ä ) 而不是 U+0041 U+0308( 大写拉丁字母 A, 组合分音符号   ̈ ) 此外,避免使用 已废弃的字符。例如,使用 U+0041 U+030A( 大写拉丁字母 A, 组合符号   ̊ ) 而不是使用 U+212B( 物理符号 : ) 。对于 Linux WWW NFC 是首选范式。
  • Normalization Form KD (NFKD): 类似 NFD, 但还要避免使用兼容性字符 (compatibility character) ,例如使用 "fi" 而不是 U+FB01(LATIN SMALL LIGATURE FI)
  • Normalization Form KC (NFKC): 类似 NFC,  但还要避免使用兼容性字符 (compatibility character) ,例如使用 "fi" 而不是 U+FB01(LATIN SMALL LIGATURE FI)

一个功能完备的字符编码转换器还 应该提供在不同范式之间进行的转换。在进行从 NFKD NFKC 的映射时需要特别注意,因为这个过程中 可 能会出现语义信息的丢失,例如字符 U+00B2( 上标 2) 会被映射成 2; 而为了维持原有语义信息,可能需要添加额外的标记信息 ( 例如,在 HTML 中为 <SUP>2<SUP>)

哪 些编程语言支持 Unicode?

大约在 1993 年之后出现的、更年轻的语言已经拥有专门用于 Unicode/ISO 10646-1 字符的内置数据类型,这包括 Ada95,Java,TCL,Perl,Python C# 及其它语言。

ISO C90 标准规定了处 理多字节编码的机制以及宽字符。这些特性在 ICO C90修正 1 得到了改善,并在 ISO C 99 准 中被进一步强化。这些特性原本是被设计用来处理各种东亚字符编码的。一方面,它们比处理 UCS 中的转移序列所需要的支持要稍复杂一些;另一方面,却又缺 少 对 UCS 中各种高级特性 ( 如组合字符 ) 的支持。 UTF-8 ISO C 标准中的多字节编码的一个实例。类型 wchar_t( 在现今环境中通常是一个 32-bit 的整数 ), 可用来存放 Unicode 字符。

不幸的是, wchar_t 在上世纪 90 年代被广泛应用于各种 16-bit 的亚洲编码之中,因此 ISO C 99 标准被向后兼容这一问题所束缚, C 无法利用类型 wchar_t 完美的支持 UCS ,如同 Java Ada95 所做到的那样。然而, C 编译器至少能够通知 应 用程序类型它所比保证的 wchar_t 在各种 locale 情况下可容纳的 UCS 值。为实现这一点,编译器会把宏 __STDC_ISO_10646__ 定义为格式为 yyyymmL 的整型常量。格式中的年份和月份用于表明已实现的 ISO/IEC 10646 及其修正的版本。例如,如果编译器实现了 ISO/IEC 10646-1 2000 的话, __STDC_ISO_10646__==200009L

Linux 下应该如何应用 Unicode?

UTF-8 出现前,全世界所有的 Linux 用户不得不使用各自语言特定的 ASCII 扩展。最流行的有欧洲范围使用的 ISO 8859-1 ISO 8859-2 ,希腊使用的 ISO 8859-7 ,俄罗斯使用的 KOI-8 / ISO 8859-5 / CP1251 ,日本使用的 EUC and Shift-JIS ,以及中国台湾省使用的 BIG5 ,等 等。这导致文档交流困 难,并且应用软件不得不考虑这些编码方式之间的各种小差别。应用程序对这些编码方式的支持通常是不完整、未经测试且难以令人满意的, 因 为开发者自身很少会使用所有这些编码方式。

由于存在这些困难,多数 Linux 发行版和开发者正逐步淘汰这些遗留编码而改用 UTF-8 。过去几年内 Linux 世界对 UTF-8 的支 持有了极大改进,现在 UTF-8 的使用已融入日常操作,如 :

  • 文本文件 ( 源代码, HMTL 文件 ,e-mail 等等 )
  • 文件名
  • 标准输入、标准输出和管道
  • 环境变量
  • 剪切和粘贴操作的缓存
  • telnet modem 和与终端模拟器间的串口通讯

以及任何其它字节序列原本被解释 为 ASCII 的应用场合。

UTF-8 模式下,终端模拟器,例如 xterm Linux 控制台驱动,将每次键盘敲击都转换为对应的 UTF-8 字节序列,并将它送至后台应用程序的标准输入。类似的,应用程序所有 在标准输出上的输出都被送至终端模拟器,在这里由 UTF-8 解码器处理后,以 16-bit 字体显示在屏幕上。

Unicode 的各种高级功能 ( 例如,阿拉伯文和印度文的高品质印刷 ) 的完备支持,只有复杂的多语种字处理软件包才会提供。 Linux 现今对 Unicode 广泛提供的支持要比这简单许多,并且其主要目的是取代旧式的 8 位和 16 位字符集。 Linux 终端模拟器和命令行工具通常只提级别 1 ISO 10646-1( 未定义组合字符 ) 实现,只支持拉丁语、希腊语、亚美尼亚语、格鲁吉亚语、 CJK 以及不需要额外处理支持的大量科学符号。处于这个实现级别 UCS ISO 8859 有很大的相似性,唯一的重大差别在于 UCS 提供了数以千记的字符,每个字符可以表示为多字节序列,还有表意的汉 字 / 日文 / 韩 文 / 字符在终端上显示 时 会占据两个字符位置 ( 双倍宽度 )

UCS
级别 2 实现 ( 对 某些特定语言,特别是 ,包含组合字符以及 Hangul Jamo) ,目前在 Linux 中部分可用 ( 也就是说,某些字体、终端模拟器和编辑器可以通过简单的 overstringing 提供支持 ) ,但是相比组合字符 序 列,应该尽可能优先考虑使用预制字符。更正式的说法是,如 Unicode技术 报告 #15 所述, Linux 下文本的 Unicode 编码应该优先采用范式 NFC

一家很有影响力的非 POSIX PC 操作系统厂商 ( 这里我们略掉它的名字 ) 曾建议所有 Unicode 文件都以字符 U+FEFF( 零宽度空白符 ) 作为起始;该字符又被称为 字节序标记 (BOM)", 用于判断文件使用的编码方式和字节序。 Linux/Unix 不使用任何 BOM 或签名。那样会 破 坏太多现有的基于 ASCII 的文法惯例 ( 例如脚本以 #! 开头 ) 。 在 POSIX 系统中,系统选定的 locale 就已经表明了程序所有的输入和输出文件预期编 码 方式。不带签名的 UTF-8 也被建议称为 "UTF-8N" 文件,但这个非标准称谓在 POSIX 世界中很少被使用。

在 转向使用 UTF-8 工作之前,先将你的系统更新为较新的具备 UTF-8 支持的发行版。如果你使用的发行版比 SuSE 9.1 Red Hat 8.0, 这一点尤为重要。在这些版本之前的发行版对 UTF-8 的支持还没有成熟到可推荐用于日常使用的程序。  

Red Hat Linux 8.0 (2000 9 ) 是第一个实现将 UTF-8 作为绝大多数 locale 默认编码这一飞跃的 Linux 发行版。唯一的例外是 Chinese/Japanese/Korean 这些 locale ,因为当时还有太多可用的专用工具尚不支持 UTF-8 UTF-8 Linux 下的这次 首 次大规模部署,导致绝大多数遗留问题在 2003 年内很快的被解决。之后 SuSE Linux  在其 9.1 (2004 5 ) 中也将 locale 的默认编码转为 UTF-8 。再之后是 Ubuntu Linux ,第一个 转 向 UTF-8 作为系统范围内默认编码的 Debian 衍生发行版。随着这三个最流向 Linux 发行版的转换,现在几乎所有维护良好的 Linux 工具中与 UTF-8 相关的 bug 都已被修正。可以预计其它发行版也会很快跟上。

 

开发者该如何修改代码?

 

如果你是一名开发者,可通过若干 种方法为程序添加 UTF-8 支持。可以将它们分为两类,这里我分别称之为软转换和硬转换。软转换 中,数 据在任何时候 都 以 UTF-8 格式被保存,只需要对代码进行很少的改动。硬转换中,程序读入的任何 数据都被转换并存放在宽字符数组中,并且在程序内部都以这种形式存在; 字符串只有在被输出时 才转换为 UTF-8 编码格式,在程序内部,所有字符都由固定长度的内存对象进行表示。

我们还可以根据程序处理字符串时 对标准库函数的依赖程度,将对 UTF-8 的支持区分为硬编码和 locale 相关两种。 C 语言提供了很多 字 符串处理函数,它们被设计成可以处理任何 locale 相关的多字节编码。一个完全依赖这些库函数的程序员,无需了解 UTF -8 编码的实际细节。很可能只需适当改变 locale 设置,就能使程序自动的也支持其它几种多字节编码 ( 例如 EUC) 。程序员可选用的另一种方式,是在代 码 中根据自己对 UTF-8 格式的了解,进行硬编码。在某些情况下这种方法能获得显著的性能提 升,对于只用来处理 ASCII UTF-8 编码的程序,也许是 最 好的选择。

即 使是在要求由 libc 对每种编码方式提供支持的情况下,为 UTF-8 格式添加额外的优化代码也是值得的。多亏了 UTF-8 的自同步特性,对它的处理可以 很有效率的 完 成。 locale 依赖的 libc 字符串函数可能比对应的硬编码函数速度慢上两个数量级。 GNU grep 就是一个反面例子;它完全依赖于 locate 相关的 libc 函数,如 mbrlen() 来提供通用多字节编码支持。这使得在多字节模式下的速度比单 字 节模式下要慢 100 倍!而其它依靠硬编码提供 UTF-8 支持的正则表达式,例如 Perl 5.8 ,则不会出现这样剧烈的性能下降。

大多数应用程序仅用软转换就可以 很好的工作于 UTF-8 环境。正是这一点使得在 Unix 中引入 UTF-8 具有可行性。举两个简单的例 子, cat echo 这样的程序不需作任何修改就能在 UTF-8 环境下工作。它们完全不受输入和输出编码方式的影响 , 无论是 ISO 8859-2 还是 UTF-8, 因为它们的工作基于字节流而不对其进行其它处理。它们只认识 ASCII 字符和 '/n' 这样的控制字符 — — 而这些字符的编码在 UTF-8 中不发生任何改变。因此,对于这些应用程序, UTF-8 的编码和解码工作完全交由终端模拟器为之完成。

而任何程序,如果是通过统计字节 数来确定字符数目,则需要对代码进行一些修改。类似于其它多字节编码方式,在涉及到 UTF-8 文本字符 串 的长度问题时,程序员必须明确区分下面三个概念:

  1. 字节数
  2. 字符数
  3. 显示宽度 ( 例如,在 VT100 终端模拟器中显示时所占据的占位符数量 )

C 函数 strlen() 总是返回字符串在内存中占据的字节数。若 strlen() 被用于该目的而被调用,不需要进行改动。

C 语言中使用 mbstowcs(NULL,s,0) 来统计字符串中的字符数,该函数具有良好的可移植性。只要设定好合适 的 locale ,该函数在 UTF- 8 环境下就能正常工作。一种计算 UTF-8 编码的字符串中字符数的硬编码方法,是统计所有值不在 0X80-0XBF 之内的字节数,因为它们只是字节而不是 独 立的字符。然而,需要计算字符数的应用场景是惊人的罕见的。

在基于 ASCII ISO 8859 的程序中, strlen() 更常见的用途是预计字符串被打印到终端时,光标移动的列数。在 UTF-8 环境下 , 无论是字节数或是字符数都无法用来预 计 字符串的显示宽度,因为表意字符 ( 汉字 / 日 文 / 韩文 ) 会 占据两列的位置,而控制字符和组合字符不占位置。为了确定一个字符串在终端屏幕显示时的宽度,需 要 对 UTF-8 字节串解码后,调用 wcwidth() 函数来测量每个字符的显示宽度,或调用 wcswidth() 来测量整个字符串的显示宽度。

举例来说 , ls 这个程序 ( 要支持 UTF-8) 必须修改代码,因为如果不知道文件名的显示宽度,它就无法以格式 化的表格形式向用户呈现目录结构。类似的,所有假设输出 由定宽字体表示并据此完成格式化的程序,都必须在 UTF-8 模式下重新学习如何计算显示宽度。编辑功能,例如删除一个字符这样的 操作,必须稍作修改以删除 该字符对应的所有字节。受此影响的包括编辑器 ( 例如 vi,emacs,realine ) 以 及使用了 ncurses 库的程序。

所有类 Unix 内核都可以很好的应用软转换,只需进行很细微的修改就可以完全支持 UTF-8

 

  • 控制台显示和键盘驱动 ( 还有 VT100 模拟器 ) 必须具备 UTF-8 编码和解码功能,并且至少要支持 Unicode 字符集的某个子 集。 Linux 自从内核 1.2 版本后就已支持这些特性 ( 发送 ESC %G 至控制台来激活 UTF-8 模式 )
  • 外部文件系统的驱动程序,例如 VFAT WinNT ,必须完成文件名编码方式的转换。 UTF-8 是可用转换选项之一,而 mount 命令必须 告 知内核驱动 : 用户进程希望看到 UTF-8 编码的文件名。由于 VFAT WinNT 已经使用 Unicode 编码, UTF-8 是唯一可选的保证无损转换的编 码 方式。
  • 所有 POSIX 系统的 tty 驱动都支持一种 "cooked“ 模式,该模式提供某些原始的行编辑功能。为了保 证 字符删除功能 (charatcer-erase) UTF-8 下正常工作,需要通过某种方式告知 tty 驱动在 "cooked“ 模式下不要将值在 0x80- 0XBF 的跟随字节视为字符,而应将它们视为一个 UTF-8 多字节序列的一部分而删除。由于内核无视 libc 提供的 lcoale 机制,需要另一种机制来告 tty 驱动来使用 UTF-8 Linux 内核 2.6 及之后的版本在类型为 termios 结构的成员变量 c_iflag 中支持一个 IUTF8 位。在其被置位时, "cooked“ 模式的行编辑器会正确的处理 UTF-8 多字节序列。可在 shell 中通过命令 "stty iutf8“ 来进入该模式。 Xterm 及类似程序在 UTF-8 环境中被调用时,应该自动将该位置位。

C 语言对 Unicode UTF-8 的支持

GNU glibc 2.2 开始,类型 wchar_t 只用于存放 32-bit ISO 10646 值,而独立于当前使用的 locale 。这一点通过对宏 __STDC_ISO_10646__ 的定义来通知应用程序,如 ISO C99 所要求的一般。 glibc2.2 或更高版本完全实现了 ISO C 的多字节转换函数 (mbsrtowcs(),wcsrtombs() ) , 可以用来在 wchar_t 和任意 locale 相关的多字节编码进行转换,包括 UTF-8,ISO 8859-1 等。

例如,你可以编写如下的程序

 
#include <stdio.h>

 
#include <locale.h>


 
int main()
 
{
 
if (!setlocale(LC_CTYPE, "")) {
 
fprintf(stderr, "Can't set the specified locale! "
 
"Check LANG, LC_CTYPE, LC_ALL./n");
 
return 1;
 
}
 
printf("%ls/n", L"Schöne Grüße");
 
return 0;
 
}


locale 设置为 LANG de_DE 并调用该程序,则程序输出为 ISO 8859-1 格式。而将 locale 设置为 LANG=de_DE.UTF-8 ,则程序输出为 UTF-8 printf 函数中的 %ls 格式说明符会 ( 隐式 ) 调用 wcsrtombs 函数来将参数中的宽字符字符串转换为 locale 特定的多字节编码格式。

C 的很多字符串函数都是 locale 无关的,它们所处理的只是以 '/0' 为结束符的字节串,例如:

strcpy strncpy strcat strncat strcmp strncmp strdup strchr strrchr
strcspn strspn strpbrk strstr strtok

这 其中的某些函数,如 strcpy ,既可以用于单字节字符集 ( ISO 8859-1) ,也可以用于多字节编码 ( UTF-8) 的字符集,因为它们完成的任务无需了解一个字符究竟对应几个字节,而其它函数 ( strchr) 完成的任务则依赖于一个 字符编码成一个字节,因此对于 UTF-8 用处不大 ( 如果在 UTF-8 字符串中寻找 ASCII 字符的话, strchr 依然能正常工 )

其它的 C 函数是 locale 相关的,在 UTF-8 locale 下同样可以正常工作,如:

 
strcoll strxfrm


UTF-8 模式该如何被激活 ?

假设你的程序属于软转换类型,没 有调用任何 C locale 相关的多字节函数 (mbsrtowcs() wcsrtombs() ) 将 所有字符转 换为 wchar_t 以用于后面的处理,有时候却必须以某种方式判明: 它所处理的文本数据,是假定为某种 8-bit 编码 ( 例 如 ISO 8859-1, 一个字节 = 一个字符 ) 还是 UTF-8 编码。只要所有人都只使用 UTF-8 ,当然可以直接设为默认方式,但是现在必须同时支持 UTF-8 和传 统的 8-bit 字符集。

最早提供 UTF-8 支持的一批应用程序,使用了各种不同的命令行开关来激活各自的 UTF-8 模式,例如著名的 xterm -u8 。事实证明这是一个糟糕的主意。记住每一个应用程序的命令行选项或其 他配置方法是非常单调乏味的 , ,因此命令行选项并不是激活 UTF-8 模式的正确 途 径。

激 活 UTF-8 模式的正确途径是利用 POSIX locale 机制。 locale 是包含特定文化中应用惯例的信息集合,包括字符编码、日期 / 时间符号、字 母 排序规则、测量体系以及普通办公纸张尺寸等。 locale 的名称通常由分别在 ISO 639-1 ISO 3166-1 中 定义的语言和国家代码组成,有时还后跟额外的编码名称或其它限定符,例如 zh_CN.utf8

命令 “locale -a” 可用来获取包含系统已安装的所有 locale( 通常位于 /usr/lib/locale/) 的列表。将 境变量 LANG 置为要选用的 locale 的名称。当 C 程序执行 setlocale(LC_CTYPE,"") 函数时,库函数会依次检查环境变量 LC_ALL LC_CTYPE LANG ,三者中的首个非空值将决定为分类 LC_TYPE( 它可以控制多字节转换函数 ) 加载哪种 locale locale 配置被分成不同类别。例如, LC_TYPE 定义字符编码,而 LC_COLLATE 定义字符串排序顺序。环境变量 LANG 为所有类别设置了默认 , 不过 LC_* 变量可用于覆盖单个类别的设置。没有必要过分在意 locale 中的国家标识符。 en_GB(English in Great Britain) en_AU(English in Australia) 这两个 locale 通常只在分类 LC_MONETARY( 货币名称,货币数额的打印规则 ) 上存在差别,而几乎没有 Linux 应用程序 会 用到这些。 LC_CTYPE=en_GB LC_CTYPE=en_AU 具有完全相同的效果。

命令 “locale charmap” 可 用来查看当前 locale 的字符编码。如果你为 LC_CTYPE 选择了一个 UTF-8 locale 的话 该命令的执行结果会是 "UFT-8" 。命令 "locale -m“ 则返回包含所有已安装编码的列表。

如果开发者完全使用 C 提供的多字节函数来完成外部字符编码和程序内部使用的 wchar_t 之间的转换的话,那么 C 的库函数则负责根据 LC_CTYPE 的值选择合适的编码,这样应用程序甚至不必明确知道使用当前的多字节 编码。


然而,如果你不希望所有 的工作都依赖于库中的多字节函数 ( 例如,因为你认为这样需要对程序进行多处修改或是效率不高 ) ,那么你的程序必须靠自己来找出何时 激 活 UTF-8 模式。为了做到这一点,在任意 X/Open 兼容系统中,头文件 <langinfo.h> 可用的情况下,可以编 写 类似下面的代码 来检测是否当前 locale 使用 UTF-8 编码 :

 
utf8_mode = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0);






当然你首先必须在程序的起始处添 加上 "setlocale(LC_CTYPE," " )" 来根据环境变量设置 locale 。命令 "locale charmap“ 同样是调用 nl_langinfo(CODESET) ,来为用户查出当前 locale 所使用的编码名称 的。 该函 数在几乎所有现代 Unix 系统上都可用。 FreeBSD 4.6 (2002-06) 之后添加了对 nl_langinfo(CODESET) 的支持。如果你需要测试 nl_langinfo(CODESET) 可用 性的 autoconf 的话,这里有 Bruno Haible 推荐的一个:

======================== m4/codeset.m4 ================================
#serial AM1


dnl From Bruno Haible.


AC_DEFUN([AM_LANGINFO_CODESET],
[
 
AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
 
[AC_TRY_LINK([#include <langinfo.h>],
 
[char* cs = nl_langinfo(CODESET);],
 
am_cv_langinfo_codeset=yes,
 
am_cv_langinfo_codeset=no)
 
])

 
if test $am_cv_langinfo_codeset = yes; then
 
AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
 
[Define if you have <langinfo.h> and nl_langinfo(CODESET).])
 
fi

])
=======================================================================


[ 你也可以不通过调用 setlocale() ,而是尝试手动查询环境变量。按照 LC ALL,LC_CTYPE,LANG 的顺序,从中 寻 找第一个值 非空的环境变量;当该值中包含“ UTF-8 这个子字符串时,将 UTF-8 模式设为默认值 ( 不过还是可以被命令 行 开关覆盖 ) ,因 为这已经可靠合理的表示 者 C 库函数已被要求使用一个 UTF-8 Locale 。以下是一段实例代码:

 
char *s;
 
int utf8_mode = 0;



 
if (((s = getenv("LC_ALL")) && *s) ||
 
((s = getenv("LC_CTYPE")) && *s) ||
 
((s = getenv("LANG")) && *s)) {
 
if (strstr(s, "UTF-8"))
 
utf8_mode = 1;
 
}

当 然这种方法依赖于所有 UTF-8 locale 的名称中都 包含编码名称,而事实并非总是如此,因此使用 nl_langinfo() 很明显是更好的选择。如果你真的担心使用 nl_langinfo() 缺少足够的可移植性,对于不提供 nl_langinfo(CODESET) 的系统还有 Markus Kuhn 编写的 费模拟器 (Bruno Haible 供了一个 ) ,开发者可以调用 norm_charmap() nl_langinfo (CODESET) 在不同平台上的输出进行标准化。]

 

如何获得UTF-8版本的xterm?

 

XFree86 4.0 或更高版本中自带 的 xterm ( Thomas Dickey 维护 ) 版 本都支持 UTF-8 。要激活 UTF-8 模式,在某个 UTF-8 locale 中运行 xterm ,并使用 ISO 10646-1 编码的字体,例如:

 LC_CTYPE=en_GB.UTF-8 xterm /
 -fn '-Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1'

在新开启的 xterm 中对某些示例文件,例如 UTF-8-demo.txt 执行 cat 命令,好好享受你所看到的吧。

如果你的 XFree86 版本低于 4.0 ,那么可以单独下载最新开发版本的 Xterm ,并且自己通过 “./configure --enable-wide-chars ; make” 或 者 “xmkmf; make Makefiles; make; make install; make install.man” 来完成编译。

如果你没有支持 UTF-8 locale ,那么启动 xterm 时加上命令行选项 -u8, 来将其输入和输出切换至 UTF-8

xterm Unicode 的支持如何 ?

XFree86 4.0.1 中的 Xterm 只在定宽字体和从左至右的书写顺序的条件西支持 ISO 10646-1 的实现级别1 ( 无组合字符 ) 。换句话说,除了能解码 UTF-8 字节序列以及使用 16-bit 字符外,终端语义与 ISO 8859-1 基本保持一致。

而到了 XFree4.0.3, 两项重要的功能被添加进来:

  • 对于 CJK 表意文字,自动转换至双倍宽度的字体
  • 对组合字符的简单加粗:

        如果选择的正常字体的尺寸为 X × Y像素,那么xterm会尝试额外加载一个尺寸为2X × Y的字体;除了具有双倍的平均宽度属性之         外,它与前者具有相同的XLFD(Xl逻辑字体描述)。xterm将用这个 字体来显示所有Unicode 技术报告 #11中确定的被赋予East           Asian Wide (W) or East Asian FullWidth (F)属性的Unicode字符。

XFree86 4.x 中附带的以下字体适用于在终端模拟器和编辑器中显式日文和韩文 Unicode 字符:

 
6x13 -Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1
 
6x13B -Misc-Fixed-Bold-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1
 
6x13O -Misc-Fixed-Medium-O-SemiCondensed--13-120-75-75-C-60-ISO10646-1
 

12x13ja -Misc-Fixed-Medium-R-Normal-ja-13-120-75-75-C-120-ISO10646-1


 

9x18 -Misc-Fixed-Medium-R-Normal--18-120-100-100-C-90-ISO10646-1
 
9x18B -Misc-Fixed-Bold-R-Normal--18-120-100-100-C-90-ISO10646-1
 

18x18ja -Misc-Fixed-Medium-R-Normal-ja-18-120-100-100-C-180-ISO10646-1
 

18x18ko -Misc-Fixed-Medium-R-Normal-ko-18-120-100-100-C-180-ISO10646-1


 

XFree86 已为环绕型组合字符 (nonspacing or enclosing combining characters , 即 那些在 Unicode 数据库 具有通用类型代码 Mn Me 的字符 ) 的提供了某种简单支持,其实现方式是简单的 加粗 ”( 逻辑或运算 ) ,每个基 字 符最多可以附加 两个组合字符。这种实现方式,对于在上方和下方附加重音符号的小号字 符,能产生可接受的表示效果;对于特别为 overstriking 设计的泰国和韩国的 Hangul Conjoining Jamo 字体,也能很好的工作。然而,在某些字体 ( 特别是 "fixed“ 字体族 ) 下,对位于大号字符之上的组合重音字符,这种方法就 无 法提供 完全令人满意的效果。因此,应继续尽可能的优先考虑使用预制字符。

XFree86 4.x 中附带的下列字体 适用于显示 Latin 等组合字符。其它字体只适用于附加于小号字符的组合重音字符。

 
6x12 -Misc-Fixed-Medium-R-Semicondensed--12-110-75-75-C-60-ISO10646-1
 
9x18 -Misc-Fixed-Medium-R-Normal--18-120-100-100-C-90-ISO10646-1
 
9x18B -Misc-Fixed-Bold-R-Normal--18-120-100-100-C-90-ISO10646-1


XFree86 4.x 中附带的下列字体适用于显示泰语中的组合字符:

 
6x13 -Misc-Fixed-Medium-R-SemiCondensed--13-120-75-75-C-60-ISO10646-1
 
9x15 -Misc-Fixed-Medium-R-Normal--15-140-75-75-C-90-ISO10646-1
 
9x15B -Misc-Fixed-Bold-R-Normal--15-140-75-75-C-90-ISO10646-1
 
10x20 -Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO10646-1
 
9x18 -Misc-Fixed-Medium-R-Normal--18-120-100-100-C-90-ISO10646-1


字体 18x18ko18x18Bko16x16Bko 16x16ko 用于显示 Hangul Jamo( 使用与泰语相同的字符 " 加粗 " 机 制 )

文本模式应用 程序的开发者需要注意:

由 于有了对 CJK 表意文字和组合字符的支持, xterm 的输出特性有些更类似于比例字体,因为一个拉丁 / 希腊 / 斯 拉夫 ( ) 字 符占一个光标位置, CJK 符占 2 个,组合字符占 0 个。 Open Group Single UNIX Specification 中定义了两个 C 函数 wcwidth() wcswidth() ,允许应用程序测试一个字符 ( 在终端输出 ) 占据几个光标位置。

 
#include <wchar.h>
 
int wcwidth(wchar_t wc);
 
int wcswidth(const wchar_t *pwcs, size_t n);


C 的库函数未提供合适功能的平台上,应用程序可以免费使用 Markus Kuhn’s 提供的对 wcwidth() 的实现。

在可以预见的未来一段时间内, Xterm 可能不会支持以下这些更复杂的、完善的 Unicode 表现引擎所提供的特性:

  • 希伯来文和阿拉伯文的双向输出
  • 阿拉伯语的替换定义表
  • substitution of Indic /Syriac ligatures
  • 组合字符的任意堆积

   
因此,希伯来和阿拉伯用 户使用的程序,在将字符串输出到终端前,必须将字符串反向并保证右对齐。换言之,双向处理必须由程序而不是 xterm 完成。与 ISO 8859 相比,希伯来文和阿拉伯文所面临的处境,至少以提供预制字符和表现表 (presentation form) 的形式得到了改善。现阶段来看,难以预测 xterm 中是否会加入双向支持以及它将具体如何工作。 ISO 6429 = ECMA-48 Unicode bidi algorithm 都提供了解决该问题的不同思路。也可参考 ECMA Technical Report TR/53

如果你打算在程序中支持双向文本 输出,可以参考 Dov Grobgeld FriBidi 或者 Mark Leisher Pretty Good Bidi Algorithm ,这是 Unicode bidi 算法的两个免费 实现。

Xterm 目前不支持阿拉伯、叙利亚或梵文的文本格式化算法,尽管 Robert Brady 已经为此发布了一些 试验性补丁 在还不确定在一个 VT100 模拟器中,支持这一特性是否可行。应用程序自身可以很轻易的应用阿拉 伯和 Hangul 格式化算法,因为 xterm 允许它们输出 必 要的表现表 (presentation form) 。对于 Hangul Unicode 中包含现代韩国表意文字 (1933 之后 ) 所 需要的表现表。对于梵文,当前 X 的字体机制甚至不支持必要ligature 变种的编码,因此 xterm 也爱莫能助。需要输出梵文或叙利亚文的应用程序,最好选用合适的 X11 绘制库,如 Pango ,而不是 xterm 这样的 VT100 模拟器。

 

从哪里可以找到ISO 10646-1 x11 字体?

 

在过于几个月中已经有很多 Unicode 字体在 X11 中变得可用,而且该名单正在迅速增长。

  • Markus Kuhn 同很多其他志愿者一起将 X11 附带的旧有的-misc-fixed-*-iso8859-1 体扩展为涵盖所 有欧洲字符 ( 拉丁语 希腊语 斯拉夫语、 注 音符号、 数学和技术符号 , 某些字体中甚至包含亚美尼亚语、 格鲁吉亚语、 片假名、 泰语以及更 ) 的字体表。更多信息请参考 Unicode fonts and tools for X11 页面。这些字体现在随 XFree86 4.0.1 或更高版本一起分发。
  • Markus 还制作了 X11R6.4 中的所有 Abobe B&H BDF 字体的 ISO 10646-1版本 这些字体已经包 含了完整的 Postscript 字体表 ( 大约 30 个额外的字符,其中大部分也被 CP 1252 MS-Windows 所使用,如智能引用和破折号等 ) 。它们原来在 ISO 8859-1 编码下是不可用的,而现在在 ISO10646-1 版本中已完全可用,并附加了很多涵盖 ISO 8859- 1,2,3,4,9,10,13,14,15 的 预制字符。这些字体现在随 XFree86 4.0.1 或更高版本一起分发。
  • XFree86 4.0 附带了一个集成的 TrueType font引擎 ,能够令采用 ISO 10646-1 编码的 X 程序使用任何 Apple/Microsoft 字体。
  • 未来的 XFree86 分发版本很有可能去除大多数旧式的 BDF 字体 , 而替换成 ISO 10646-1 编码的版本。 X 服务器则会增加一个自动编码转换器;当旧式的 8 位软件需要使用旧式字体编码时,它会根据其 ISO 10646-1 版本的字体文件 对用户透明的、 动态的创建 ISO 8859-*  字体编码。 现 代软件应该优先直接使用 ISO 10646-1 字 体编码。
  • ClearlyU (cu12) 是 由 Mark Leisher 提供的一个 12 point 100dpi 的用于 X11 ISO 10646-1 编码的成比例 BDF 字体 (示例 图像 )
  • 日本的 Electronic Font Open Laboratory 也 致力于 Unicode 点阵字体族的工作。
  • Dmitry Yu. Bolkhovityanov 提供了一个 BDF 格式的 Unicode VGA font , 用于在 IBM PC 模拟器等中使用。
  • Roman Czyborra GNU Unicode font 项 目的目标是整理出一个完整、免费的 8×16/16×16 像素的 Unicode 字体。目前已包含超过 34000 个字符。
  • etl-unicode 一个 ISO 10646-1 编码的 BDF 格式的字体,由 Primoz Peterlin 提供。
  • Primoz Peterlin 还 发起了 freefont 目,借 助于 PfaEdit URW++ 捐赠给 ghostscript 项目的 35 个核心 PostScript 轮廓字体中的某些进行了扩展,使其具有更好的 UCS 涵盖性。
  • George Williams 提供了 Type1 Unicode font family ,其也有 BDF 格式。他还开发了 PostScript 和点阵字体编辑器 PfaEdit
  • EversonMono 一个包含超过 3000 个欧洲字符的共享的等宽字体,可以从 DKUUG server 获得。
  • Birger Langkjer Linux 提供了一个 Unicode VGA Console Font
  • Alan Wood 给出了支持不同 Unicode 值域的 Microsoft 字体 的清单。
  • CODE2000 James Kass 提供的一个 Unicode 字体。

Unicode X11 字体名字以 -ISO10646-1 结尾,该值已成为所有 Unicode ISO 10646-1 16-bit 字体对应的 X 逻辑字体描述符 (XLFD) CHARET_REGISTERY CHARSET_ENCODING 这两个域的 正式注册值 。每个 *-ISO10646-1 字体涵盖了整个 Unicode 字符集中的某个子集,而用户必须清楚选择哪个字体能够涵盖他们所需要 的字符子集。

*-ISO10646-1 字体通常也指定了一个 DEFAULT_CHAR 值,指向一个特殊的非 Unicode 字形,用于表示该字体不支 持 的字符 ( 常是一 个 虚线框,一个 H 的大小,定位于 0x00) 。这保证用户至少能意识到此处有一个不被支持的字符。 xterm 所使用的较小的定宽字体如 6x13 等,永远不可 能 涵盖所有 Unicode 字符,因为很多语言,例如日文,只有在字体的像素尺寸与欧洲用户广泛 使用的大很多的情况下才能被表示。用于欧洲字符的典型 Unicode 字体只包 含 1000 3000 的字符子集,例如 CEN MES-3 repertoire

你 可能注意到, ASCII 引用标记的形状 *-ISO10646-1 字体中发生了细微的变化,这是为了与其它平台上的标准和习惯保持一 直。

 

与UTF-8 终端模拟器相关的问题有哪些?

 

VT100g 终端模拟器可接受 ISO 2022(=ECMA-35 ) 转义序列,用于在不同字 符集间切换。

ISO 2022 的角度看, UTF-8 另一套编码系统 "( 参见 ECMA 35 15.4 ) UTF-8 位于 ISO 2022 SS2/SS3/G0/G1/G2/G3 的世界之外,因此如果从 IS0 2022 切换至 UTF-8 的话,所有的 SS2/SS3/G0/G1/G2/G3 状态信息都变得无意义,直到离开 UTF-8 模式并切换回 ISO 2022 为止。 UTF-8 是一种无状态编码,即一个自结束的字节序列就完全确定了要表示的字 符,而不用依赖任何转换状态。 ISO 10646-1 中的 G0 G1 ISO 8859-1 中的一样,而 G2/G3 ISO 10646-1 中并不存在,因为每个字符在码表中的位置固定,切换不会发生。在 UTF-8 模式下,终端不会因为载入某个二进制文件而意外的切换至奇怪的图 形 字符模式。这使得一个终端在 UTF-8 模式下比在 ISO 2022 模式下具备好得多的健壮性,因此能将终端锁定于 UTF-8 模式而不会意外切换回 ISO 2022 的话,是会很有用的。

ISO 2022 标准规定了一系列的 ESC% 序列,用于离开 ISO2022 模式而切换至其它编码系统,很多这样的用于 UTF-8 的序列已经被注册进入 ISO 2375 International Register of Coded Character Sets

  • ESC %G ,从 ISO2022 环境下激活一个 UTF-8 模式 ( 对 实现级别无要求 ) ,并允许再次返回 ISO 2022 模式。
  • ESC %@ ,在 UTF-8 模式下输入该序列的话,则从 UTF-8 模式返回 IS02022 模式。
  • ESC %/G ,切换至实现级别1的 UTF-8 模式,不允许返回。
  • ESC %/H ,切换至实现级别二的 UTF-8 模式,不允许返回。
  • ESC %/I ,切换至实现级别三的 UTF-8 模式,不允许返回。

终端模拟器处于 UTF-8 模式下时,输入的任何 ISO 2022 转义序列例如 G2/G3 切换等都被其忽略。终端模拟器唯一会处理的 ISO 2022 转义序列是 ESC %@ ,用于从 UTF-8 返回 ISO 2022

UTF-8 仍然允许你使用像 CSI 这样的 C1 控制字符 , 尽管 UTF-8 也使用 0X80-0X9F 之间的字节。重要的是要明白, UTF-8 模式下的终端模拟器在解释执行任何控制字符前,必须先对输入的 字 节流进行 UTF-8 解码。 C1 字符同其它大于 U+007F 的字符一样要先被解码。

很多现在可用的文本模式应用程 序,它们期望于与使用旧式编码的终端进行交互,或者使用 ISO 2022 转义序列用于切换终端字体。为了使这些应用程序在 UTF-8 终端模拟器中可用,可能需要使用一个执行 ISO 2022 UTF-8 之间动态转换的中间转换层,例如 Juliusz Chroboczek 发布的 luit and pluto 如果你对于一个 UTF-8 终端的要求仅是对 ISO 8859 的支持的话,还可以使用 Michael Schröder and Jürgen Weigert 提供的 screen (4.0 或更新版本 ) 。由于实现 ISO 2022 是一个很复杂而且容易出错的任务,开发者最好避免由自己来实现 ISO 2022 ,而只是实现 UTF-8 模式;对于需要 ISO 2022 的用户则建议他们利用 luit 或是 screen

支 持 UTF-8 的应用程序有哪些 ?

警告:自 2003 年年中开始,这一部分日趋变得不完备。支持 UTF-8 ,已成为大多数维护良好的软件包的标准特性。这份清单很快就会被 转 变为最流行的存在 UTF-8 相关问题的软件清单。

终端模拟器和通讯

 

  • XFree86 4.0 或更高版本分发的 xterm UTF-8 locale 下能工作,条件是用户要选择一种 *-iso10646-1 字体。尝试运行一下 "LC_CTYPE=en_GB.UTF-8 xterm -fn '-Misc-Fixed-Medium-R-Normal--18-120-100-100-C-90-ISO10646-1' "
  • C-Kermit 7.0 后支持 UTF-8 作为传输、终端和文件字符集。
  • mlterm 一个多语言的终 端模拟器,支持 UTF-8 和很多其它编码、组合字符、 XIM
  • Edmund Grimley Evans BOGL Linux 帧缓冲图形库进行了扩展,增加了对 UCS 字体的支持,并利用其开发了一个名为 bterm 的简单的 UTF-8 控制台终端模拟器。
  • Uterm 一个用于 Linux 帧缓冲控制台的 UTF-8 终端模拟器。
  • [ 新增内容 ] Juliusz Chroboczek’s 提供的 Pluto , 一个超凡的 Unicode 转换器,能够检测一个终端 session 中使用的编码,并透明的转换为 UTF-8( 这对于使用混杂着 ISO 8859 UTF-8 消息的 IRC 频道来说,太美妙了! )

编辑和字处理

  • Vim ( 一个流行的经典 编 辑器 vi 的克隆版 ) 自版本 6.0 后支持 UTF-8 宽字符,以及最多两个组合字符 ( 连用 )
  • Emacs 版本 21.3 后具备对 UTF-8 良好的基本支持。等到尚在进行的在 Emacs23 中将 Emacs/MULE 的内部编码完全转换为 UTF-8 的工作完成后, 该 状况会得到显著改善。 ( 某些较旧的 21.x 版本中通过 mule-utf-8 编码系统来提供实验性质的 UTF-8 支持,只有在适当配置的前提下才能工作。 最 好升级到至少 Emacs 21.3 ,这样在默认配 置下就可以在 UTF-8 模式下很好的工作 )
  • Yudit Gaspar Sinai 编写的免费 X11 Unicode 编辑器。
  • Thomas Wolff 编 写的 Mined 2000 是一款非常优秀的支持 UTF-8 的文本编辑器,它领先于其它竞争者之处不仅在于支持双倍宽度和组合字 符,而且还支持双向文 字、为很多语种提供键盘映射以及语种相关的高亮表示等特性。
  • JOE 一款流行的仿 wordStar 的编辑器,自版本 3.0 起支持 UTF-8
  • Cooledit 版本 3.15.0 后提供 UTF-8 UCS 支持。
  • QEmacs 一个用于 UTF-8 终端的轻量级编辑器。
  • less 一个流行的纯文 本文件查看器,自版本 348 后支持 UTF-8( 版本 358 中存自一个与处理 UTF-8 字符相关的 bug 对此已有相应的 patch 版本 381 中在搜索模式的输入行中对 UTF-8 字符仍然存在问题 )
  • GNU bash and readline 都提供了单行编 辑器, bash 自版本 2.05b readline 自版本 4.3 后键入了对多字节编码的支持,例如 UTF-8
  • gucharmap UMap 用于在程序中选 择和粘贴 Unicode 字符的工具。
  • [ 新 加内容 ]LaTeX 2004 3 月 后在基 本包中支持 UTF-8( 仍是实验性的 ) 。你可以简单的写“ /usepackage[utf8]{inputenc}& ”,然后就至 少 能对你的 LaTex 源文件中包含的属于 Tex 标准字符表的字符采用 UTF-8 编码 ( 在 此之前, UTF-8 通过使用 Dominique Unruh 提 供的软件包就可用,该软件包涵盖了更多的字符,对资源的消耗很大 )
  • Abiword .

编程

  • Perl 5.8.1 起就提供了实用的 Unicode UTF-8 支持。内存中的文本串加上了标记,标明是字节串或是字符串,后者在内 部以 UTF-8 的格式存储而从程序员的角 度 来看则是 UCS 字符序列。现在又包含了对编码转换和范式的全面支持。详情参阅 "man perluniintro"
  • Python 版本 1.6 中增加了对 Unicode 的支持。
  • Tcl/Tk 版本 8.1 开始使用 Unicode 作为基础字符集。
  • CLISP 在所有多字节编 码 ( 包括 Unicode) 下工作,并提供了类似于 wcwidth() wcswidth() API 函数 char-width() string-width()

邮件和互联网

 

  • 邮件客户端 Mutt 版本 1.3.24 后就可以在 UTF-8 locale 下正常工作。如果编译和链接时加上 ncurses ( ncurses库的基础上键入了宽字符支持 ) 话, Mutt 1.3.x UTF-8 locale 中可以在 xterm 这样的 UTF-8 终端模拟器中很好的工作。
  • Exmh MH nmh 邮件系统的 GUI 前端,自版本 2.1.1 开始部分支持 Unicode ,条件是使用 8.3.3 或更新版本 Tcl/Tk 。要显 UTF-8 格式的 email ,请确认已安装 *- iso10646-1字体 .Xdefaults 中添加一行 “exmh.mimeUCharsets: utf-8” Exmh 内部的大多数 MIME 字符集功能仍保留在 Tcl 8.1 之前的样子,因而忽略了 Tcl/Tk 提供的最新的 Unicode 支持;而原本这些是可以被简化和得到显著改善的。尤其是撰写或是回复 UTF-8 件,现在仍然不 支持。
  • 大多数现代 web 浏览器,如 Mozilla Firefox ,现在都对 UTF-8 有良好的支持。

打印

  • Cedilla Juliusz Chroboczek 提供的 Unicode PostScript best-effort 文本打印程序
  • Markus Kuhn’s 编写的 hpp 一个简单的纯文 本转换器,可用于支持在 C 语言库中存在对应的 locale 的所有字符编码中被标准 PCL 定宽字体所覆盖的 符表 HP PCL 打印机。
  • Markus Kuhn 编写的 utf2ps 一个较早出现的 带有概念验证性质、敏捷实现的用于 PostScript UTF 格式化工具,该程序只是用来证明哪个 字符表 仅使用标准 PostScirpt 字体的条件性就能很轻松的打印出来,而绝不应该用于实际应用。
  • CUPS(通用 Unix打印系统 ) 附带了一个将 UTF-8 纯文本转换为 PostScript 的工具 :texttops
  • Serge Winitzki 编写的 txtbdf2ps 一个使用 BDF 像素字体将 UTF-8 纯文本打印成 PostScript Perl 脚本。

其它

  • PostgreSQL DBMS 自版本 7.1 后就不仅支持 UTF-8 作为前端编码,同样支持作为后台的存储编码。前端与后台编码之间的数 据转换是自动进行的。
  • FIGlet 一个使用等宽字 符作为块图形元素,输出大尺寸标题文本的工具,在版本 2.2 中添加了对 UTF-8 的支持
  • Charlint 一个用于 W3C 字符模型 字符规范化工 具。
  • 第一批 Unix 下可用的 UTF-8 工具源自于 Plan 9 —— 贝尔实验室 Unix 的继承者同时也是世界上第一个使用 UTF-8 的操作系统。 Plan 9 中的编辑器 Sam 终端模拟器 9term 被移植到了 Unix 下。 Wily 始是作为 Plan 9 中的编辑器 Acme Unix 下的实现,它为程序员提供了一个面向鼠标、基于文本的工作环境。最近 出现了 Plan 9 from User Space 个软件包,将很 多 Plan 9 程序从原生的 Plan 9 环境中移植到了类 Unix 操作系统中。
  • 表格工具 Gnumeric 版本 1.1 开始就完全基于 Unicode
  • The Heirloom Toolchest 是一套标准 Unix 工具,它在原有的由 Caldera 开源方式发布的 工具的基础上,增加了对多字节编码特别是 UTF-8 的支持。
  • convmv 一个用于将整个 目录树中所有旧式编码的文件名转换为 UTF-8 编码的工具。

用 于改善 UTF-8 支持的补丁有哪些 ?

在各主要发行版中已经包含了很多 这样的补丁。

  • OpenI18N ( 以前的 Li18nux) 项目下的高级工具开发小组已为诸如 cut,fold,glibc,sed,uniq,xterm 等各种工具提供了可改善 UTF- 8 支持的国际化补丁程序。
  • Bruno Haible 编写的 Unicode-HOWTO 收集了各种工具 的 UTF-8 补丁以及统计各种程序对 UTF-8 支持状态的列表。
  • Bruno Haible 还为 stty,linux 内核 tty 等制作了各种 补丁程序
  • 文本模式 web 浏览器 w3m 多语言化补丁 (w3m-m17n) 允许用户在类似 xterm UTF-8 终端中以统一编码来查看文档 ( 按下 "o" 键后 ) 。 此外还有 多语言版本的 w3m (w3mmee) ( 未曾试用 )

有 没有用于处理 Unicode 的免费库 ?

  • Ulrich Drepper 发布的 GNU C library glibc 版本 2.2 之后就实现了对 UTF-8 的充分支持,一个 ISO 14651 排序算法,并且可以重新编码为很多其它编码形式。当前所有 Linux 发行版都附带 glibc 2.2 或更高版本,因此如果你仍在使用比这更早个 Linux C library 的话,绝对应该马上升级。
  • International Components for Unicode (ICU) 已成为世界上可能是最强大的提供高级 Unicode 字符处理功能的跨平台标准库。
  • X.Net 提供的 xIUA 软件包 的设计目的是通过提供 locale 管理机制来改造现有代码,以获取 ICU 的支持;这样开发者就不必修改内部调用接口用于传递 locale 参数。它使用更熟悉的 API ,例如使用 xiua_strcoll 来进行分配,并且是线程安全的。
  • Mark Leisher 提 供的 UCDATA Unicode 字符属性 和 bidi 库以及 wchar_t 类型的测试代码。
  • Bruno Haible 提供的字符集转换库 libiconv 供了一个 iconv() 现,可用于缺少 该实现的系统中或者存在实现,却无法完成到 / Unicode 的转换。它还包含了字符编码查询库 libcharset ,可以允许应用程序以一种具备良好可移植性的方式查询当前 lcoale 所使用的编码 方 式,避免了直接使用 nl_langinfo(CODESET) 带来的移植性问 题。
  • Bruno Haible 写的 libutf8 提供了处理 UTF-8 串的各种函数,特别是为尚未提供合适的 UTF-8 locale 平台。
  • Tom Tromey 供 的 libunicode GNOME 项目的组成部分,但也可以被独立构建。它包含了各种字符类和转换函数 (CVS )
  • FriBidi 是由 Dov Grobgeld 提供的 Unicode bidi 算法的免费实现。
  • Markus Kuhn 提供了 wcwidth() 的免费实现 ,用于判断一个字符在 UTF-8 终端模拟器的屏幕上会占据几个光标位置;在 C 库尚未提供对等功能的平台中,应用程序可以利 用 该免费实现。
  • Markus Kuhn 编写的 transtab 那些必须尽全力 完成从 Unicode ASCII 或其它 8-bit 字符集转换的应用程序提供的一个表 。 该表中含有全面的 Unicode 字符的替代串,类似于人们经常在 email 或打字机中用于表示无可用字符的回退标记 (fallback notation) 。该表以 ISO/IEC TR 14652 的 格式被分发,以保证可以很容易的被 POSIX locale 定义文件所 包含。

各 种 X widget 库对于 Unicode 支持的现状如何 ?

哪 些支持 UTF-8 的软件包正处于开发阶段 ?

  • Emacs 23 计划内部完全使用 UTF-8 编码。如果你有兴趣参与或测试的话,请加入邮件列表emacs-devel @gnu.org。
  • Linux Console Projec t 致力于在内核中加入修正版的 VT100 模拟器,这将改善现有的 UTF-8 的过分简单化的支持

Solaris UTF-8 的支持如何 ?

Solaris 版本 2.8 开始就至少部分支持 UTF-8 。要使用 UTF-8 模式,只需设定好某个 UTF-8 locale, 例如在 C shell 中输入:

setenv LANG en_US.UTF-8

这 样,终端模拟器 dtterm 就可用来输入和输出 UTF-8 文本,打印过滤器 mp 就能在 PostScript 打印机上打印 UTF-8 文件。目前, locale en_US.UTF-8 Motif CDE 桌面应用程序和库所支持,但并不被 OpenWindows,XView OPENLOOK 桌面应用程序和库所支持。

更多信息请参考 SUN Overview of en_US.UTF-8 Locale Support 网页。

UTF-8 可以应用于 Web ?

是 的。 HTTP 服务器可以通过两种方式告知客户某个文档采用了 UTF-8 编码:

  •   保证传输该文档的 HTTP 头部中包含如下内容
 

Content-Type: text/html; charset=utf-8


这适用于 HTML 文件;对于纯文本文件,则要变为

 

Content-Type: text/plain; charset=utf-8

如何实现上述要求取决于你使用的 Web 服务器。如果使用 Apache 并且有一个子目录,其中存放的素有 .html .txt 文件都采用 UTF-8 编码的 话, 在该目录下创建一个 .htaccess 文件并在其中添加以下两行 :

    Addtype text/html; charset=UTF-8 html
    Addtype text/plain;charset=UTF-8 txt

网站管理员可以修改 /etc/httpd/mime.types ,对所有子目录同时完成相同的修改。                                                                            

  • 如果你无法影响 Web 服务器如何自动在文档之前添加 HTTP 头部的话,那么就在 HTML 文档的 HEAD 元素中添加

        <META http-equiv=Content-Type content="text/html; charset=UTF-8">
        
    这样就能产生相 同的效果。很显然这种方法只对 HTML 文件有效,而无法应用于纯文本文件;而且,该方式只能在解析器已经开 始读取文件内容后才能告知解析器 该文件使用的编码格式。因此,相比之下,该方式显然不如前者优雅。  

目前最广泛使用的浏览器对 UTF-8 的有足够好的支持,因而通常推荐在网页中采用 UTF-8 编码。陈旧的 Netscape 4 浏览器使用了一种犯人的单一大号字体来显示所有 UTF-8 文档。最好升级到 Mozilla Netscape 或其它较新的浏览器 (Netscape 4 总体来看有很多 bug 而且已停止了维护 )

还 有一个问题, HTML 表单中输入的非 ASCII 字符在随后的将内容发送给服务器某个 CGI 脚本的 GET POST 请求中该如何编码 ? 不幸的是无论在标 准 还是实现领域,正如 Alan Flavell 单提交与国际化指南 中所探讨的一般,这个问题依然一片混乱。我们只能寄望于最终会出现一 套在 UTF-8 下解决这一切的惯例。也可参考 Mozilla bug 18643 的 相关讨论。

 

PostScript的字形名字与UCS码值是怎么关联在一起的?

 

参考 Adobe Unicode and Glyph Names 指南

有 没有已制定好的 Unicode 子集 ?

对包含 40000 个以上字符的 Unicode 进行完整和全面的实现,这是一个庞大的工程。然而,很多情况下 ( 尤其对于欧洲市场 ) 同之前 一 样只实现几 百或几千字符就足够了,而且仍然享受 Unicode 所提供的的单一简单编码覆盖所有需要字符的简洁性。已经有很多不同的 UCS 子集被制定出来:


  • Windows Glyph List 4.0 (WGL4) 是一个容量为 650 的字符表,它涵盖了所有 Microsoft 以前使用的所有 8-bit MS-DOS,Windows,Mac ISO 码值页。现在所有 Windows 字体都至少覆盖了 WGL4 字符表。 WGL4 CEN MES-1 的超集 (WGL4 测试文件 )
  • 欧洲标准委员会 CEN/TC304 CWA 13873 中定义了 UCS 的三个欧洲子集: MES-1, MES-2 MES-3
    • MES-1 是一个很小的含 335 个字符的 (Unicode ) 拉 丁语子集。它恰好包含了 ISO 6937 中的所有字符再 加上欧元符号。这意味着 MES-1 包含了 ISO 8859 part 1,2,3,4,9,1,15 中的全部字符 [ 注意,如果目的仅是提供最简单、最低成本的合理 UCS 中欧子集,我会选择实现 MES-1 外加以下 14 个在 Windows 码值页 1252 之中却不在 MES-1 之中的字符: U+0192, U+02C6, U+02DC, U+2013, U+2014, U+201A, U+201E, U+2020, U+2021, U+2022, U+2026, U+2030, U+2039, U+203A]
    • MES-2 是一个包含 1052 个拉丁语 / 希腊语 / 叙利亚语 / 亚美尼亚语 / 格鲁吉亚语字符的子集。它涵盖了欧洲 ( 不止是欧 !) 欧洲语言国 家使用的所有语言和所有 8-bit 码值页。它还附加了一个在技术文档中使用的数学符号的很小集合。 MES-2 MES-1 的超集。如果只面向欧洲或西方市场进行开发, MES-2 是推荐使用的字符表。 [ 注意 : 由 于奇怪的政治原因,下面 8 WGL4ZI 字符不在 MES-2 之中: U+2113, U+212E, U+2215, U+25A1, U+25AA, U+25AB, U+25CF, U+25E6 。如果你要实现 MES-2 ,绝对应该附加支持这 8 个字符,这样就能附加实现对 WGL4 的兼容 ]
    • MES-3 是一个包含 2819 个字符、非常全面的 UCS 子集。它将所有对欧洲用户有潜在使用可能的 UCS 字符包含进来。 它 是为更有野心的实现者提供的。 MES-3 MES-2 WGL4 的超集。
  • JIS X 0221-1995 为日本用户定义了 7 个不相交的 UCS 子集 :
    • Basic Japanese (6884 characters): JIS X 0208-1997, JIS X 0201-1997
    • Japanese Non-ideographic Supplement (1913 characters): JIS X 0212-1990 non-kanji, plus various other non-kanji
    • Japanese Ideographic Supplement 1 (918 characters): some JIS X 0212-1990 kanji
    • Japanese Ideographic Supplement 2 (4883 characters): remaining JIS X 0212-1990 kanji
    • Japanese Ideographic Supplement 3 (8745 characters): remaining Chinese characters
    • Full-width Alphanumeric (94 characters): for compatibility
    • Half-width Katakana (63 characters): for compatibility
  • ISO 10646 标准将其字符表分成若干的 collection 用于定义和实现 子集。 Unicode 定义了类似但并不一致的 字符块 对应于 Unicode 标准中的 section
  • RFC 1815 是 由某个家伙 1995 年提交的备忘录,他显然并不喜欢 ISO 10646 并且当时未意识到 JIS X 0221-1995 的存在。该备忘录中讨论了一个称之为 “ISO-10646-J-1” UCS 子集,它由 14 UCS collection 组成,其中的某些与 JIS X 0208 存在交集。它只是一个在 Windows NT 1995 年的某个日语版本中偶然实现的特殊字体。 RFC 1815 现在已是完全过时和不相干,最好被忽略。
  • Markus Kuhn ucs-fonts.tar.gz 定义了三个 UCS 子集: TARGET1, TARGET2, TARGET3 。他们是相应 MES 子集的合理扩展,是该 xterm 字体包完成的基础。

Markus Kuhn 编写的 Perl 脚本 unise 许对 UCS 子集进行方便的集合运算,它对于想要定义一个新的 UCS 子集或是检查某个实现的覆盖范围的用户很有用。

在 不同编码方式之间进行转换时需要考虑哪些问题 ?

Unicode 协会维护了一组 Unicode 和其它旧有编码标准之间的 映射关系表 重要的是要明白,这些映 射表的主要目的是展示 Unicode 是被映射的旧有编码的超集,并记录为了保证对旧有字符集的 round-trip 兼容而纳入 Unicode 标准的那些 字 符背后的动机和起源。优秀的字符编码转换函数应完成的任务,远比盲目的应用这些示例映射表复杂的多!这是因为某些字符集中一致的字符在其它字符集中却被 区 分。

Unicode
映射表只 在一定程度上适用于将文本直接由旧式编码转换为 Unicode 。然而高端的转换工具应该提供交互机制,使得在旧式编码中一致而在 Unicode 中被区分的字符可以被逐个的交互式或半自动的消除歧义。

Unicode 到旧式字符集的反向转换需要以上映射表的多对一扩展。在很多旧式编码 中,若干 Unicode 字符必须被映射至单一 码值。 Unicode 会目前并未为此而维护标 准多对一表,而且也没有为字符集转换工具定义任何标准行为。

以下是一些从 Unicode 转为其它形式时必须解决的多对一映射的例子:

UCS characters

equivalent character

in target code

U+00B5 MICRO SIGN
U+03BC GREEK SMALL LETTER MU

0xB5

ISO 8859-1

U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
U+212B ANGSTROM SIGN

0xC5

ISO 8859-1

U+03B2 GREEK CAPITAL LETTER BETA
U+00DF LATIN SMALL LETTER SHARP S

0xE1

CP437

U+03A9 GREEK CAPITAL LETTER OMEGA
U+2126 OHM SIGN

0xEA

CP437

U+03B5 GREEK SMALL LETTER EPSILON
U+2208 ELEMENT OF

0xEE

CP437

U+005C REVERSE SOLIDUS
U+FF3C FULLWIDTH REVERSE SOLIDUS

0x2140

JIS X 0208

从现有标准化信息中可以近似的生 成类似的多对一映射表,然而对这些映射表仍必须进行手动扩展和修订。例如,似乎显而易见, IBM PC 字符集中 0XE1 原本既被当作小写 beta 使用 ( 因 为它在码表中位于 alpha gamma 之间 ) , 也被当作德语的 sharp-s 字符使用 ( 因为当在德语键盘上按下 sharp-s 键时生成该值 ) 。类似的, 0XEE 既可以是数学符号 属于 " , 也可以是一个 small epsilon 。这些字 符并不是 Unicode 标准等价字符,因为尽管它们在低解析度字体下看起来很相似,然而在高 质量印刷中它们是完全不同的字符。 IBM CP437 提供的 映射 体现了一种用途,而微软提供的 射表 则体现了另一种用途 ; 两者具备同等的合理性。一个优秀的转换器在从 Unicode 进行转换时,应该做到对二者都兼容,而不是盲目 的 只使用 Microsoft 的映射表。

Unicode database filed 5 包含了字符分解映射 (Character Decomposition Mapping) ,可用于自动生成上述示例的某些映射。作为一条规则, Unicode 至其它字符集的转换输出,必须与输入的 Unicode 字符是否采用范式 NFC 关。要查询汉语、日文、 韩文 Han/Kanji/Hanja 的等价信息,可使用 Unihan database 。 对于上述例子中的 IBM PC 字符,标准映射表并未提供足够的映射;此时在 Unicode book 中对外形近似字符的交叉引用,则成为等价映射有价值的参考来源。最 后,究竟选用哪种映射是个人喜好问题。

Unicode 协会曾维护了至 CJK 字符集的映射表,但已经宣布它们是过时和废弃的,这事因为它们在 Unicode Web 服务器上的存在而导致了一大批幼稚、不完整的转换器被开发出来。要特 别指出的是,现已废弃的 CJK Unicode 映射表, 在某些情况下必须进行轻微的修改来保留组合 ( 字符 ) 编 码中的信息 ( 完整性 ) 。例如,标准映射表为 ASCII-Unicode- ASCII ,以及 JIS X 0208-Unicode-JIS X 0208 的转换链提供了 roung-trip 兼容性。然而, EUC-JP 编码同时涵盖了 ASCII JIS X 0208 ,而 ASCII 映射表和 JIS X 0208 映射表在一个字符上存在重叠,即 U+005C( 反向分割符 '/') 。因此 EUC-JP 转换器必须使用一个略微修改过的 JIS X 0208 映射表,使得 JIS X 0208 中的 0X2140( 对应 EUC-JP 中的 0XA1 0XC0) 被映射到字符 U+FF3C( 全宽度反向分割符 ) 。。这样就保证从 EUC-JP Unicode 再到 EUC-JP 的过程中不会出现信息的丢失 , round-trip 兼容性。 Unicode 标准附录 #11 就该问题提供了进一步的指导。另一个存在的问题是它同旧有映射表存在 兼容性问题,这点在 Tomohiro Kubota 一篇短文 中有相关解释。

除了使用标准规范映射表外,编码 转换器的开发者还可以提供对转译 ( transliteration) 的 支持。转译的意思一个将 Unicode 字符在目标编码中转换为一个在图形和 ( ) 语 义上相似的字符,即使这两者规范化 (normalization) 后 在 Unicode 中是不同的字符。例子如下:

UCS characters

equivalent character

in target code

U+0022 QUOTATION MARK
U+201C LEFT DOUBLE QUOTATION MARK
U+201D RIGHT DOUBLE QUOTATION MARK
U+201E DOUBLE LOW-9 QUOTATION MARK
U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK

0x22

ISO 8859-1

Unicode 协会当前并没有提供或维护任何标准转译表 CEN/TC304 有一份有关建议使用的 ASCII 回撤字符的 “European fallback rules” 草 案正在制定中,但还尚未成熟。现有可用的 Unicode 转译表可从 Bruno Haible libiconv glibc 2.2 locales Markus Kuhn transtab 中找到。

X11 对使用 Unicode 已经准备就绪了么?

X11 R7.0 release (2005) X 协会对 X11 Window System 标准最新版本的示例实现。目前大部分的 X11标准 以及 部分示例实现仍然没有未 跟上在 Unix 下使用 Unicode 的广泛兴趣。

这其中已经得到修正的包括:

  • Keysyms: X11R6.9 之后, X窗口系统协议规 的附录 A 中为每个 Unicode 字符分配了一个 keysym 值。任何码值界于 U+00000100 U+00FFFFFF 之间的 UCS 字符可以表示为 0x01000100 0x01FFFFFF 之间的 keysym 值。该方案是由 Markus Kuhn 1998 年提出的,并且已被很多应用程序 ( 最早是 xterm) 支持了很多年。修订后的附录 A 现在在其 pre-Unicode 的旧式 keysyms 表中还包含了一个正是的 UCS 交叉引用列。
  • UTF-8 locales X11R6.8 添加了对 UTF-8 的支持。
  • X11R6.8 中增加了很多广泛使用的 Unicode 标准字体,而且这些字体现在被某些经典的标准工具所支持,例如 xterm

对于 Unicode 用户, X11 标准还存在许多问题;其示例实现中还存在某些不方便之处,仍然需要在 某个后继 X11 版本中得到修正:

 

  • UTF-8 剪 切和粘贴 : ICCCM 标准依然没有确定如何转 递选中的 UCS 字符。某些生产商选择将 UTF-8 作为另一种编码方式添加到现有的 复合文本机制 (CTEXT) 中。这并不是一个好的解 决方案,原因至少有三:                                                                                          
    • CTEXT 是一个相当复杂的 ISO 2022 机制,并且 Unicode 所提供的机会不只是对 CTEXT 提供一个扩展,而是用另一种简单的多、更方便而且同样强大的机制来替 代这个庞然大物。  
    • 很多现有的应用程序能够通过 CTEXT 交流所选内容,但并不支持新增的 UTF-8 CTEXT 的使用者必须选择是使用旧 式 的 ISO 2022 编码还是新增的 UTF-8 编码,但二者无法同时使用。换言之,将 UTF-8 加入 CTESX 严重破坏了与现有 CTEXT 程序的向后兼容性。
    • 当前的 CTEXT 规范甚至在第六节明确禁止添加 UTF-8 复合文本中不使用其它在 ISO 中注册 的 编码系统;扩展段是使用 ISO 2022 编码的唯一机 制。 “                                                                                                                                        
    Juliusz Chroboczek 起草了一份对 ICCCM 进行扩展的建议草案 Inter-Client Exchange of Unicode Text  ,通过加入一个新的可用于属性类型和选择目标的 UTF8_STRING 来处理 UTF-8 选择 ( 区 域 ) 。这种方法利落的解决了上述所有问题。 UTF8_STRING 同现有的 STRING( ISO 8859-1 字符串保留使用 ) 一样的无状态和易用,并且增加一个新的选择对象允许应用程序同时以旧 有的 CTEXT 和新增的 UTF8_STRING 格两种格式提供选择区域,这使得协同工作能力最大化。 选 择区域的持有者和请求者之间可以对 UTF8_STRING 的使用进行协商,无论如何也不会导致兼容性问题。 Markus Kuhn 已制作好了一个 ICCCM patch , 它向标准中添加了必要的定义。当前情况, UTF8_STRING 已在 X.Org 正是注册,我们希望在未来的某个版本中 ICCCM 有相应的更新。                      
  • 用程序窗口属性 :为了帮助窗口管理器正确的为窗口进行标注, ICCCM 2.0规范 要求应用程序为每个窗口对类似 WM_NAME, WM_ICON_NAME WM_CLIENT_MACHINE 这样的属性赋值。旧有的 ICCCM 2.0 (1993) 将这些属性的类型定义为多态类型 TEXT ,这意味着它们可以使用类型 STRING(ISO 8859-1) COMPOUND_TEXT(ISO 2022 的一个子集 ) C_STRING( 未知字符集 ) 之一,表明采用的文本编码。单纯添加 UTF8_STRING 作为 TEXT 的可选项会破坏对那些不知 道 有该类型的旧有窗口管理器的向后兼容性。因此, freedesktop.org 窗口管理器规范项目 定的 标准草案 外添加了窗口属性如 _NET_WM_NAM _NET_WM_ICON_NAME 等,它们的类型为 UTF8_STRING
  • 低效率的字体数据结构 Xlib API X11 协议中用于表示字体度量信息的数据结构,在处理稀疏分布的字体时极度 缺乏效 率。最常用 X Client 中访问字体最常用的方式是调用 XLoadQueryFont() ,它会为一个 XFontStruct 分配空间并从 Server 提取其内容。 XFontStruct 中包含一个元素为 XCharStruct(12 字节 ) 的 数组。数组的大小等于字体中最后一个字符的码值减去第一个字符 的码值后再加 1 。因此,任何同时包含 U+0020 U+FFFD “*-iso10646-1” 字体,即使它只 涵 盖了 1000 个字符,也会导致分配一个拥有 65502 个元素的数组,这意味着 786KB 的客户端内存和数据传输。

迄今为止采用了某些变通方法 :

  •  
    • XFree86 4.0 中附带的非亚洲的 -misc-fixed-*-iso10646-1 字体不包含码值超过 U+31FF 的字符。这将内存需求减至 153KB ,虽然仍然 不 良,但少了很多 ( 实际上在 BDF 文件中有很多有用的字符其码值超过了 U+31FF, 等待着这个问题某一天被解决;但是现在他们都被编码为 -1 因此被 X server 忽略。如果你需要使用这些字符,那就安装没有应用 "BDF 裁减 " 原始字体 ) 。                                                                                                        
    • XFree86 4.0.3 开始,对 BDF 字体的检测还可以通过在 XLFD 尾部附加字符码值范围来完成,这在 XLFD规范 3.1.2.12 这一节有详细说明,例如:

      -Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO10646-1[0x1200_0x137f]

      这样只会加 载 BDF 字体中埃塞俄比亚语的部分,从而产生一个很小的 XFontStruct 。更早版本的 X server 会 简单的忽略字体的子集括号,并加载完整字体,因而使用该方法不存在 向后兼容性问题。                                                
    • Bruno Haible XFree86 4.0 编写了一个 BIGFONT 扩展协议,它对 XChaStruct server client 间执行了压缩传输,并在若干个装载相同字体的 client 之间使用 Xlib 的共享内存。

这些变通并没有解决 XFontStruct 不适用于稀疏分布字体这一底层问题,但是他们的确提供了显著的效率改 善,而不需改变任何 API Client 源码。真正的解决方案应该是用某个稍微更灵活的、包含有序线性表或哈 希表而不是数组的数据结构扩展或取代 XFontStruct 。 对 XFontStruct 的重新设计,同时还为增加急需的组合字符和 ligature 提供了可能性。

另一种方法则是引入一种新的字体编码,例如可以称之为 “ISO10646-C”( 这里的 C 表示 combing,complex,compact character-glyph mapped, 随你的便 ) 。在这种编码中,为每个字形分配的数值是真正的字体相关的字形值,而 不是任何 UCS 码值的等价物。应用程序要利用这种新的字体编 码 的话,需要配合使用一些高效的完成字符 - 字形码值映射的 C 函数:

  •  
    • makeiso10646cglyphmap(XFontStruct *font, iso10646cglyphmap *map)
      从字体属性 中读取字符 - 字形映射,并存入一个紧凑和高效的内存表示。
    • freeiso10646cglyphmap(iso10646cglyphmap *map)
      释放指定的 内存表示。
    • mbtoiso10646c(char *string, iso10646cglyphmap *map, XChar2b *output)
      wctoiso10646c(wchar_t *string, iso10646cglyphmap *map, XChar2b *output)
      输入一个 Unicode 字符串,通过将它转换为 XChar2b 字形串,该字形串适合于被 XDrawString 使用从参数 iso10646cglyphmap 中提取的 ISO10646-C 字体用于输出。

ISO10646-C 字体仍被限制为不能包含 超过 64K 个字形,但是它们可以来自于 UCS 的任何位置,而不只是 BMP 。这种解决 方 案还轻易的提供了字形替代特性,这样我们终于可以处理印度字体了。它解决了 ISO 10646-1 的超大 XFontStruct 问题,因为现在该结构所 占 空间与字形数成线性关系,而不是最大码值。它还可以提供组合字符的简单 " 加 粗 " ,不过这样在 ISO 10646-C 字体中组合字符必须以负宽度存储。它甚至可以通过为同一个组合字符提 供若干个位于不同高度的组合字型,来支持可变的组合字符位置。

待办事项:为 ISO 10646-C 属性编写规范,编写映射函数的示例实现,并将其添加入 xterm GTK 和其它应用程序和库。志愿者?

  • 组合字符 : X11 规范不以任何方式支持组合字符。字体信息中缺少必要的数据来完成高质 量、自动的重音放置操作 ( 正如在所有的 Tex 字体中所发现的那样 ) 。很多人试验了通过 使 用在原始字符左侧带有墨点的零宽度字符来实现最简单的组合字体 " 加 粗 " ,但详细如何做到这一则点细节不祥 ( 例如,零宽度字符在 CharCell Monospaced 字体中被允许么? ) ,因此这还不是一个广泛接受的惯例。
  • Ligatures:   印度文字需要支持 ligature 替换的字体文件格式,而这同组合字符一样,完全超出了当前 X11 规范的范围。

XFree86 小组几位成员一直在围绕这些问题展开工作。 X.Org 个开放团体,作为 X 协会的官方继承者以及 X11 标准及其示例实现的管理者,已经 ( 或者仍在考虑 ) 接收了这些工作成果。

X11 规范不以任何方式支持组 合字符。字体信息中缺少必要的数据来完成高质量、自动的重音放置操作 ( 正 如在所有的 Tex 字体中所发现的那样 ) 。很多人试验了通过 使 用在原始字符左侧带有墨点的零宽度字符来实现最简单的组合字体 " 加 粗 " ,但详细如何做到这一则点细节不祥 ( 例如,零宽度字符在 CharCell Monospaced 字体中被允许么? ) ,因此这还不是一个广泛接受的惯例。

至于与字体相关的问题,解决方案 很可能会是完全丢弃旧式的服务端字体机制而改而使用 XFree86 新提供的 Xft 另一项正在进行中相关工 作是 Sun 正在开发的 准类型服务 (ST)

什 么是在 UTF-8 下工作的 Perl one-liner?

以下例子是基于两点假设:使用 Perl 5.8.1 或更新版本,以及使用 UTF-8 locale( "locale charmap“ 命令输出 "UTF-8")

对 于 Perl 5.8.0, 不需要使用选项 '-c' ;下面的例子不带 '-c' 的话无法在 UTF-8 locale 下工作。你真的不应该再使用 Perl 5.8.0, 因为它对 Unicode 的支持存在很多 bug

在标准输出上打印欧元符号 (U+20AC)

  perl -C -e 'print pack("U",0x20ac)."/n"'
  perl -C -e 'print "/x{20ac}/n"'           # works only from U+0100 upwards

查找畸形的 UTF-8 序列 :

  perl -ne '/^(([/x00-/x7f]|[/xc0-/xdf][/x80-/xbf]|[/xe0-/xef][/x80-/xbf]{2}|[/xf0-/xf7][/x80-/xbf]{3})*)(.*)$/;print "$ARGV:$.:".($-[3]+1).":$_" if length($3)'

查找非 ACII 字节 :


  perl -ne '/^([/x00-/x7f]*)(.*)$/;print "$ARGV:$.:".($-[2]+1).":$_" if length($2)'

将非 ASCII 字符转换为 SGML/HTML/XML 风格的对字符码值的 10 进制表示 ( 例如,将 ‘Ş’ 转换为 &#350)



  perl -C -pe 's/([^/x00-/x7f])/sprintf("&#%d;", ord($1))/ge;'

将用 10(16) 进制码值引用的字符转换为 UTF-8

  perl -C -pe 's/&/#(/d+);/chr($1)/ge;s/&/#x([a-fA-F/d]+);/chr(hex($1))/ge;'

 


我 怎样才能输入 Unicode 字符 ?

  有很多方法可以用于输入标准键盘上没有的 Unicode 字符。

独立于应用程序的方法

  • 在一个小文件中将你最常用到的 Unicode 字符按照最符合应用的方式安排好,要用的时候执行复制和粘帖操作。对 于相对而言很少 用到的非常特殊的字符,例如更为深奥的数学运算符,这通常是最方便和 最合适的方法。
  • 使用 xmodmap 对键盘映射进行扩展。如果你的键盘上有专用于此的 AltGr 键的话,这种方法会非常方便;某些 US 键盘上没有 AltGr 而只有右 Alt 键,而其它键盘则很不幸的完全没有类似键。创建包含如下条目的 ~/.Xmodmap 文件,并在 X11 的启动脚本中通过加入 ” xmodmap ~/.Xmodmap” 将 该文件载入 X server  
 
keysym d = d NoSymbol degree NoSymbol
 

keysym m = m NoSymbol emdash mu
 

keysym n = n NoSymbol endash NoSymbol
 
keysym 2 = 2 quotedbl twosuperior NoSymbol
 
keysym 3 = 3 sterling threesuperior NoSymbol
 
keysym 4 = 4 dollar EuroSign NoSymbol
 
keysym space = space NoSymbol nobreakspace NoSymbol
 
keysym minus = minus underscore U2212 NoSymbol
 
keycode 34 = bracketleft braceleft leftsinglequotemark leftdoublequotemark
 
keycode 35 = bracketright braceright rightsinglequotemark rightdoublequotemark
 
keysym KP_Subtract = KP_Subtract NoSymbol U2212 NoSymbol
 
keysym KP_Multiply = KP_Multiply NoSymbol multiply NoSymbol
 
keysym KP_Divide = KP_Divide NoSymbol division NoSymbol

现在你会发现借助于 AltGr 键,能够很容易的通过键盘输入下列字符:

AltGr+d

°

AltGr+

NBSP

AltGr+[

AltGr+]

AltGr+{

AltGr+}

AltGr+2

²

AltGr+3

³

AltGr+-

AltGr+n

AltGr+m

AltGr+M

µ

AltGr+keypad-/

÷

AltGr+keypad-*

×

上述例子文件是基于 UK 键盘的,不过可以很容易的修改为其它键盘布局并自由选择映射的字符。  

  • ISO 14755 中 定义了一种 16 进制的输入方法 : 在按下 Ctrl Shift 键的同时输入 16 进制的 Unicode 码值;释放 Ctrl Shift 键后,就完成了对应的 Unicode 字符的输入。

        这种方法目前在 GTK+2 中得到了实现,并在 GNOME 终端, Mozilla Firefox 中可用。

依赖于应用程序的方法

  • VIM 中,依次输入 ‘Ctrl-V’ ‘u' 16 机制数字,例  Ctrl-V u 20ac
  • Microsoft Windows 中,按下 Alt 键的同时,输入十进制 Unicode 码值 ( 前 面附加小键盘上的 0) 。例如,按下 Alt |输入 08364 |释放 Alt I
  • Microsoft Word 中,输入 16 进制 Unicode 码值,然后按 Alt+X 可将其转为对应的 Unicode 字符。例如, 20ac Alt-X

关 于这个话题有哪些好的邮件列表 ?

你当然应该订阅邮件列表 linux-utf8@nl.linux.org 。这是一个所有致力于改进 GNU/Linux Unix 系统和应用程序 UTF-8 支持的人们进行交流的场 所。 订阅方法是,发送主题为 "subscribe 的信件 " linux-utf8-request@nl.linux.org 你也可以通过 web接口 进行订阅和浏览存档。

还有邮件列表 unicode@unicode.org ,这里是搜寻 Unicode 标准的作者和很多其它 guru 的发言最佳场所。订阅方 式, 是发送主题为 "subscribe“ ,内容为 ”subscribe YOUR@EMAIL.ADDRESS unicode“ 的 信件至 unicode-request@unicode.org

现在用于讨论 Xlib X server Unicode 支持的相关邮件列表是 xorg@xorg.org 。过去在 xfree86.org 的邮件列表中还包括 fonts i18n 它们的存档中仍包含着有 价值的信息。

更多参考

Be aware that each translation reflects only some past version of this document , which I update several times per month and revise more thorougly once or twice each year.

我会经常为该文档的添加新的内 容,因此请定期来查看。非常欢迎关于改进的建议。请为在自由软件社区中传播 UTF-8 的重要性贡献一份力 量。

特别感谢 Ulrich Drepper, Bruno Haible, Robert Brady, Juliusz Chroboczek, Shuhei Amakawa, Jungshik Shi, Robert Rogers 和很多其它人提供了有价值的注释 , 还有 SuSE GmbH, Nürnberg 的支持。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值