Linux 版 (精华区)
发信人: don (驿路梨花), 信区: Linux
标 题: locale下如何应用Unicode
发信站: 紫 丁 香 (Tue May 9 10:32:01 2000), 转信
发信人: null (钠尔), 信区: LINUX
标 题: locale下如何应用Unicode
发信站: 碧海青天 (Fri May 5 13:37:22 2000), 转信
在 Linux 下该如何使用 Unicode?
在 UTF-8 之前, 不同地区的 Linux 用户使用各种各样的 ASCII 扩展.
最普遍的欧洲编码是 ISO 8859-1 和 ISO 8859-2, 希腊编码 ISO 8859-7,
俄国编码 KOI-8, 日本编码 EUC 和 Shift-JIS, 等等. 这使得
文件的交换非常困难, 且应用软件必须特别关心这些编码的不同之处.
最终, Unicode 将取代所有这些编码, 主要通过 UTF-8 的形式. UTF-8
将应用在
文本文件 (源代码, HTML 文件, email 消息, 等等)
文件名
标准输入与标准输出, 管道
环境变量
剪切与粘贴选择缓冲区
telnet, modem 和到终端模拟器的串口连接
以及其他地方以前用ASCII来表示的字节串
在 UTF-8 模式下, 终端模拟器, 比如 xterm 或 Linux console driver,
将每次按键转换成相应的 UTF-8 串, 然后发送到前台进程的 stdin 里.
类似的, 任何进程在 stdout 上的输出都将发送到终端模拟器,
在那里用一个 UTF-8 解码器进行处理, 之后再用一种 16
位的字体显示出来.
只有在功能完善的多语言字处理器包里才可能有完全的 Unicode
功能支持. 而广泛用在 Linux 里用于取代 ASCII 和其他 8
位字符集的方案则要简单得多. 第一步, Linux
终端模拟器和命令行工具将只是转变到 UTF-8. 这意味着只用到 级别1
的 ISO 10646-1 实现 (没有组合字符),
且只支持那些不需要更多处理的语言象 拉丁, 希腊, 斯拉夫
和许多科学用符号. 在这个级别上, UCS 支持与 ISO 8859 支持类似,
唯一显著的区别是现在我们有几千种字符可以用了,
其中的字符可以用多字节串来表示.
总有一天 Linux 会当然地支持组合字符, 但即便如此,
对于组合字符串, 预写字符(如何可用的话)仍将是首选的. 更正式地,
在 Linux 下用 Unicode 对文本编码的首选的方法应该是定义在 href="http://www.un
icode.org/unicode/reports/tr15/">Unicode Technical
Report #15
里的 Normalization Form C.
在今后的一个阶段,
人们可以考虑增加在日文和中文里用到的双字节字符的支持 (他们相对比较简单),
组合字符支持, 甚至也许对从右至左书写的语言如希伯来文 (他们可不是那么简单的)
的支持. 但对这些高级功能的支持不应该阻碍简单的平板 UTF-8 在
拉丁, 希腊, 斯拉夫和科学用符号方面的快速应用, 以取代大量的欧洲
8 位编码, 并提供一个象样的科学用符号集.
我该怎样修改我的软件?
有两种途径可以支持 UTF-8, 我称之为软转换与硬转换. 软转换时,
各处的数据均保存为 UTF-8 形式, 因而需要修改的软件很少.
在硬转换时, 程序将读入的 UTF-8 数据转换成宽字符数组,
以在应用程序内部处理. 在输出时, 再把字符串转换回 UTF-8 形式.
大多数应用程序只用软转换就可以工作得很好了. 这使得将 UTF-8
引入 Unix 成为切实可行的. 例如, 象 cat 和 echo
这样的程序根本不需要修改. 他们仍然可以对输入输出的是 ISO 8859-2
还是 UTF-8 一无所知, 因为它们只是搬运字节流而没有处理它们.
它们只能识别 ASCII 字符和象 '\n' 这样的控制码, 而这在 UTF-8
下也没有任何改变. 因此, 这些应用程序的 UTF-8
编码与解码将完全在终端模拟器里完成.
而那些通过数字节数来获知字符数量的程序则需要一些小修改. 在
UTF-8 模式下, 它们必须不数入 0x80 到 0xBF 范围内的字节,
因为这些只是跟随字节, 它们本身并不是字符. 例如, ls
程序就必须要修改,
因为它通过数文件名中字符数来排放给用户的目录表格布局. 类似地,
所有的假定其输出为定宽字体, 并因此而格式化它们的程序,
必须学会怎样数 UTF-8 文本中的字符数. 编辑器的功能,
如删除单个字符, 必须要作轻微的修改,
以删除可能属于该字符的所有字节. 受影响有编辑器 (vi,emacs,
等等)以及使用
ncurses 库的程序.
Linux 核心使用软转换也可以工作得很好,
只需要非常微小的修改以支持 UTF-8. 大多数处理字符串的核心功能 (例如:
文件名, 环境变量, 等等) 都不受影响. 下列地方也许必须修改:
控制台显示与键盘驱动程序 (另一个 VT100 模拟器)
必须能编码和解码 UTF-8, 必须要起码支持 Unicode 字符集的几个子集.
从 Linux 1.2 起这些功能已经有了.
外部文件系统驱动程序, 例如 VFAT 和 WinNT 必须转换文件名字符编码.
UTF-8 已经加入可用的转换选项的列表里了, 因此 mount
命令必须告诉核心驱动程序用户进程希望看到 UTF-8 文件名. 既然 VFAT
和 WinNT 无论如何至少已经用了 Unicode了, 那么 UTF-8
在这里就可以发挥其优势, 以保证转换中无信息损失.
POSIX 系统的 tty 驱动程序支持一种 "cooked" 模式,
有一些原始的行编辑功能. 为了让字符删除功能工作正常, stty
必须在 tty 驱动程序里设置 UTF-8 模式, 因此它就不会把 0x80 到 0xBF
范围内的跟随字符也数进去了.
Bruno Haible 那里已经有了一些 stty 和核心 tty 驱动
程序的 Linux 补丁
了.
C 对 Unicode 和 UTF-8 的支持
从 GNU glibc 2.1 开始, wchar_t
类型已经正式定为只存放独立于当前 locale 的, 32位的 ISO 10646 值. glibc
2.2 开始将完全支持 ISO C 中的多字节转换函数 (wprintf(),mbstowcs(),等等),
这些函数可以用于在 wchar_t 和包括 UTF-8 在内的任何依赖于 locale
的多字节编码间进行转换.
例如, 你可以写
wprintf(L"Sch鰊e Gre!\n");
然后, 你的软件将按照你的用户在环境变量 LC_CTYPE (例如,
en_US.UTF-8 或 de_DE.ISO_8859-1) 中选择的 locale
所指定的编码来打印这段文字. 你的编译器必须运行在与该 C
源文件所用编码相应的 locale 中,
在目标文件中以上的宽字符串将改为 wchar_t 字符串存储. 在输出时,
运行时库将把 wchar_t 字符串转换回与程序执行时的 locale 相应的编码.
注意, 类似这样的操作:
char c = L"a";
只允许从 U+0000 到 U+007F (7 位 ASCII) 范围里的字符. 对于非 ASCII 字符,
不能直接从 wchar_t 到 char 转换.
现在, 象 readline() 这样的函数在 UTF-8 locale 下也能工作了.
--
--
一条驿路,一种氛围。
一朵梨花,一种思考。
希望能在Linux这条驿路上与你同行!
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.118.239.63]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.274毫秒