📄 unicode.htm
字号:
两种编码方式下是一样的.</li>
<li>所有 >U+007F 的 UCS 字符被编码为一个多个字节的串,
每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F)
不可能作为任何其他字符的一部分.</li>
<li>表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD
的范围里, 并指出这个字符包含多少个字节.
多字节串的其余字节都在 0x80 到 0xBF 范围里.
这使得重新同步非常容易, 并使编码无国界,
且很少受丢失字节的影响.</li>
<li>可以编入所有可能的 2<sup>31</sup>个 UCS 代码</li>
<li>UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP
字符最多只用到 3 字节长.</li>
<li>Bigendian UCS-4 字节串的排列顺序是预定的.</li>
<li>字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到.</li>
</ul>
<p>下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode
中的序号.</p>
<div align="center"><center>
<table BORDER="1">
<tr>
<td>U-00000000 - U-0000007F: </td>
<td>0<i>xxxxxxx</i> </td>
</tr>
<tr>
<td>U-00000080 - U-000007FF: </td>
<td>110<i>xxxxx</i> 10<i>xxxxxx</i> </td>
</tr>
<tr>
<td>U-00000800 - U-0000FFFF: </td>
<td>1110<i>xxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> </td>
</tr>
<tr>
<td>U-00010000 - U-001FFFFF: </td>
<td>11110<i>xxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> </td>
</tr>
<tr>
<td>U-00200000 - U-03FFFFFF: </td>
<td>111110<i>xx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> </td>
</tr>
<tr>
<td>U-04000000 - U-7FFFFFFF: </td>
<td>1111110<i>x</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i> 10<i>xxxxxx</i>
</td>
</tr>
</table>
</center></div>
<p>xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x
具有越少的特殊意义.
只用最短的那个足够表达一个字符编码数的多字节串.
注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.</p>
<p><strong>例如</strong>: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8
里的编码为:</p>
<blockquote>
<p>11000010 10101001 = 0xC2 0xA9</p>
</blockquote>
<p>而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为:</p>
<blockquote>
<p>11100010 10001001 10100000 = 0xE2 0x89 0xA0</p>
</blockquote>
<p>这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 <strong>U</strong>CS <strong>T</strong>ransformation
<strong>F</strong>ormat. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8)
来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身.</p>
<h2>什么编程语言支持 Unicode?</h2>
<p>在大约 1993
年之后开发的大多数现代编程语言都有一个特别的数据类型, 叫做
Unicode/ISO 10646-1 字符. 在 Ada95 中叫 Wide_Character, 在 Java 中叫 char.</p>
<p>ISO C 也详细说明了处理多字节编码和宽字符 (wide characters) 的机制,
1994 年 9 月 <a href="http://www.lysator.liu.se/c/na1.html">Amendment 1 to ISO C</a>
发表时又加入了更多. 这些机制主要是为各类东亚编码而设计的,
它们比处理 UCS 所需的要健壮得多. UTF-8 是 ISO C
标准调用多字节字符串的编码的一个例子, <em>wchar_t</em>
类型可以用来存放 Unicode 字符.</p>
<h2>在 Linux 下该如何使用 Unicode?</h2>
<p>在 UTF-8 之前, 不同地区的 Linux 用户使用各种各样的 ASCII 扩展.
最普遍的欧洲编码是 ISO 8859-1 和 ISO 8859-2, 希腊编码 ISO 8859-7,
俄国编码 KOI-8, 日本编码 EUC 和 Shift-JIS, 等等. 这使得
文件的交换非常困难, 且应用软件必须特别关心这些编码的不同之处.</p>
<p>最终, Unicode 将取代所有这些编码, 主要通过 UTF-8 的形式. UTF-8
将应用在
<ul>
<li>文本文件 (源代码, HTML 文件, email 消息, 等等)</li>
<li>文件名</li>
<li>标准输入与标准输出, 管道</li>
<li>环境变量</li>
<li>剪切与粘贴选择缓冲区</li>
<li>telnet, modem 和到终端模拟器的串口连接</li>
<li>以及其他地方以前用ASCII来表示的字节串</li>
</ul>
<p>在 UTF-8 模式下, 终端模拟器, 比如 xterm 或 Linux console driver,
将每次按键转换成相应的 UTF-8 串, 然后发送到前台进程的 stdin 里.
类似的, 任何进程在 stdout 上的输出都将发送到终端模拟器,
在那里用一个 UTF-8 解码器进行处理, 之后再用一种 16
位的字体显示出来.</p>
<p>只有在功能完善的多语言字处理器包里才可能有完全的 Unicode
功能支持. 而广泛用在 Linux 里用于取代 ASCII 和其他 8
位字符集的方案则要简单得多. 第一步, Linux
终端模拟器和命令行工具将只是转变到 UTF-8. 这意味着只用到 级别1
的 ISO 10646-1 实现 (没有组合字符),
且只支持那些不需要更多处理的语言象 拉丁, 希腊, 斯拉夫
和许多科学用符号. 在这个级别上, UCS 支持与 ISO 8859 支持类似,
唯一显著的区别是现在我们有几千种字符可以用了,
其中的字符可以用多字节串来表示.</p>
<p>总有一天 Linux 会当然地支持组合字符, 但即便如此,
对于组合字符串, 预作字符(如何可用的话)仍将是首选的. 更正式地,
在 Linux 下用 Unicode 对文本编码的首选的方法应该是定义在 <a
href="http://www.unicode.org/unicode/reports/tr15/">Unicode Technical Report #15</a>
里的 <em>Normalization Form C.</em></p>
<p>在今后的一个阶段,
人们可以考虑增加在日文和中文里用到的双字节字符的支持 (他们相对比较简单),
组合字符支持, 甚至也许对从右至左书写的语言如希伯来文 (他们可不是那么简单的)
的支持. 但对这些高级功能的支持不应该阻碍简单的平板 UTF-8 在
拉丁, 希腊, 斯拉夫和科学用符号方面的快速应用, 以取代大量的欧洲
8 位编码, 并提供一个象样的科学用符号集.</p>
<h2>我该怎样修改我的软件?</h2>
<p>有两种途径可以支持 UTF-8, 我称之为软转换与硬转换. 软转换时,
各处的数据均保存为 UTF-8 形式, 因而需要修改的软件很少.
在硬转换时, 程序将读入的 UTF-8 数据转换成宽字符数组,
以在应用程序内部处理. 在输出时, 再把字符串转换回 UTF-8 形式.</p>
<p>大多数应用程序只用软转换就可以工作得很好了. 这使得将 UTF-8
引入 Unix 成为切实可行的. 例如, 象 cat 和 <samp>echo</samp>
这样的程序根本不需要修改. 他们仍然可以对输入输出的是 ISO 8859-2
还是 UTF-8 一无所知, 因为它们只是搬运字节流而没有处理它们.
它们只能识别 ASCII 字符和象 '\n' 这样的控制码, 而这在 UTF-8
下也没有任何改变. 因此, 这些应用程序的 UTF-8
编码与解码将完全在终端模拟器里完成.</p>
<p>而那些通过数字节数来获知字符数量的程序则需要一些小修改. 在
UTF-8 模式下, 它们必须不数入 0x80 到 0xBF 范围内的字节,
因为这些只是跟随字节, 它们本身并不是字符. 例如, <samp>ls</samp>
程序就必须要修改,
因为它通过数文件名中字符数来排放给用户的目录表格布局. 类似地,
所有的假定其输出为定宽字体, 并因此而格式化它们的程序,
必须学会怎样数 UTF-8 文本中的字符数. 编辑器的功能,
如删除单个字符, 必须要作轻微的修改,
以删除可能属于该字符的所有字节. 受影响有编辑器 (<samp>vi,emacs</samp>,
等等)以及使用 <samp>ncurses</samp> 库的程序.</p>
<p>Linux 核心使用软转换也可以工作得很好,
只需要非常微小的修改以支持 UTF-8. 大多数处理字符串的核心功能 (例如:
文件名, 环境变量, 等等) 都不受影响. 下列地方也许必须修改:
<ul>
<li>控制台显示与键盘驱动程序 (另一个 VT100 模拟器)
必须能编码和解码 UTF-8, 必须要起码支持 Unicode 字符集的几个子集.
从 Linux 1.2 起这些功能已经有了.</li>
<li>外部文件系统驱动程序, 例如 VFAT 和 WinNT 必须转换文件名字符编码.
UTF-8 已经加入可用的转换选项的列表里了, 因此 <samp>mount</samp>
命令必须告诉核心驱动程序用户进程希望看到 UTF-8 文件名. 既然 VFAT
和 WinNT 无论如何至少已经用了 Unicode了, 那么 UTF-8
在这里就可以发挥其优势, 以保证转换中无信息损失.</li>
<li>POSIX 系统的 tty 驱动程序支持一种 "cooked" 模式,
有一些原始的行编辑功能. 为了让字符删除功能工作正常, <samp>stty</samp>
必须在 tty 驱动程序里设置 UTF-8 模式, 因此它就不会把 0x80 到 0xBF
范围内的跟随字符也数进去了. <a href="http://clisp.cons.org/~haible/">Bruno
Haible</a> 那里已经有了一些 <samp>stty</samp> 和核心 tty 驱动 程序的 <a
href="ftp://ftp.ilog.fr/pub/Users/haible/utf8/">Linux 补丁 </a>了.</li>
</ul>
<h2>C 对 Unicode 和 UTF-8 的支持</h2>
<p>从 GNU glibc 2.1 开始, <samp>wchar_t</samp>
类型已经正式定为只存放独立于当前 locale 的, 32位的 ISO 10646 值. glibc
2.2 开始将完全支持 ISO C 中的多字节转换函数 (wprintf(),mbstowcs(),等等),
这些函数可以用于在 wchar_t 和包括 UTF-8 在内的任何依赖于 locale
的多字节编码间进行转换.</p>
<p>例如, 你可以写</p>
<pre> wprintf(L"Sch鰊e Gr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -