为什么在与UNIX / Linux环境交互时使用UTF-8编码?

时间:2008-10-02 20:31:04

标签: linux unix encoding

我知道这是习惯,但为什么?是否存在真正的技术原因,为什么任何其他方式都是一个非常糟糕的想法,还是仅仅基于编码和向后兼容的历史?此外,不使用UTF-8的危险是什么,还有一些其他编码(最值得注意的是,UTF-16)?

编辑:通过互动,我主要是指shelllibc

8 个答案:

答案 0 :(得分:15)

部分原因是文件系统期望NUL('\ 0')字节终止文件名,因此UTF-16不能很好地工作。您必须修改大量代码才能进行更改。

答案 1 :(得分:8)

正如jonathan-leffler所提到的,主要问题是ASCII空字符。传统上,C期望字符串为空终止。因此,标准C字符串函数将阻塞任何包含等于ASCII null(0x00)的字节的UTF-16字符。虽然您可以使用广泛的字符支持进行编程,但UTF-16不是filenames, text files, environment variables中适合的Unicode外部编码。

此外,UTF-16和UTF-32都具有大端和小端方向。要解决此问题,您需要外部元数据,如MIME类型或Byte Orientation Mark。它指出,

  

透明地使用UTF-8的地方   在8位环境中,使用BOM   会干扰任何协议或   期望特定的文件格式   开头的ASCII字符,   比如使用“#!”在...   Unix shell脚本的开头。

UTF-16的前身,称为UCS-2,不支持代理对,具有same issues。应避免使用UCS-2。

答案 2 :(得分:2)

我认为这主要是UTF8用ASCII提供的向后兼容性。

对于“危险”问题的答案,您需要通过“互动”来指定您的意思。你的意思是与shell,libc或内核进行交互吗?

答案 3 :(得分:2)

现代Unix使用UTF-8,但并非总是如此。在RHEL2上 - 只有几年的历史 - 默认是

$ locale
LANG=C
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=
C / POSIX语言环境应该是一个7位ASCII兼容的编码。

然而,正如Jonathan Leffler所说,任何允许在字符序列中使用NUL字节的编码在Unix上都是不可行的,因为系统API是区域无知的;假设字符串都是由\ 0。

终止的字节序列

答案 4 :(得分:1)

我相信当微软开始使用双字节编码时,尚未分配0xffff以上的字符,因此使用双字节编码意味着没有人不必担心字符长度不同。

现在有这个范围之外的字符,所以你不得不处理不同长度的字符,为什么有人会使用UTF-16?我怀疑如果他们今天设计了他们的unicode支持,微软会做出不同的决定。

答案 5 :(得分:0)

是的,这是出于兼容性原因。 UTF-8向后兼容ASCII。 Linux / Unix是基于ASCII的,所以它只是有意义的。

答案 6 :(得分:0)

我认为7位ASCII很好。

说真的,Unicode在事物的方案中相对较新,而UTF-8向后兼容ASCII,并且对于典型文件使用较少的空间(一半),因为它每个代码点(字符)使用1到4个字节,而UTF-16每个代码点(字符)使用2或4个字节。

由于宽度更简单,UTF-16更适合内部程序使用。它的前身UCS-2对于每个代码点都是2个字节。

答案 7 :(得分:0)

我认为这是因为期望ASCII输入的程序将无法处理UTF-16等编码。对于大多数字符(在0-255范围内),这些程序将高字节视为NUL / 0字符,它在许多语言和系统中用于标记字符串的结尾。在UTF-8中不会发生这种情况,UTF-8旨在避免嵌入式NUL并且与字节顺序无关。