代码之家  ›  专栏  ›  技术社区  ›  Carl

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

  •  11
  • Carl  · 技术社区  · 17 年前

    我知道这是惯例,但为什么呢?有没有真正的技术原因可以解释为什么其他方法会是一个非常糟糕的主意,或者仅仅是基于编码和向后兼容性的历史?另外,不使用的危险是什么 UTF-8 但是其他一些编码(最显著的是, UTF-16 )?

    编辑:通过互动,我主要是指 shell libc .

    8 回复  |  直到 11 年前
        1
  •  15
  •   Jonathan Leffler    11 年前

    部分原因是文件系统希望nul(“\0”)字节终止文件名,因此utf-16无法正常工作。你必须修改很多代码才能做出改变。

        2
  •  8
  •   Joseph Holsten    17 年前

    正如JonathanLeffler提到的,主要问题是ASCII空字符。C通常希望字符串以空结尾。因此,标准的C字符串函数将阻塞任何包含等同于ASCII空值(0x00)的字节的UTF-16字符。虽然您当然可以用宽字符支持编程,但utf-16不是一个合适的Unicode外部编码 filenames, text files, environment variables .

    此外,utf-16和utf-32都有大尾数和小尾数方向。要处理这个问题,您要么需要像mime类型这样的外部元数据,要么 Byte Orientation Mark . 它指出,

    其中,utf-8在 8位环境,使用BOM 会干扰任何协议或 需要特定的文件格式 开始的ASCII字符, 例如使用“!”在 Unix shell脚本的开头。

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

        3
  •  2
  •   Mike F    17 年前

    我认为它主要是utf8与ascii的向后兼容性。

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

        4
  •  2
  •   ephemient    17 年前

    现代的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结尾的字节序列。

        5
  •  1
  •   Mark Baker    17 年前

    我相信,当微软开始使用双字节编码时,还没有分配超过0xffff的字符,所以使用双字节编码意味着没有人需要担心字符的长度不同。

    既然已经有了超出这个范围的字符,那么无论如何,您必须处理不同长度的字符,为什么会有人使用UTF-16?我怀疑微软会做出不同的决定,如果他们今天正在设计他们的Unicode支持。

        6
  •  0
  •   Steve K    17 年前

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

        7
  •  0
  •   Cade Roux    17 年前

    我认为7位ASCII是可以的。

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

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

        8
  •  0
  •   Juan Pablo Califano    17 年前

    我认为这是因为期待ASCII输入的程序将无法处理诸如UTF-16之类的编码。对于大多数字符(在0-255范围内),这些程序将高字节视为nul/0字符,在许多语言和系统中用于标记字符串的结尾。这种情况在UTF-8中不会发生,它的设计是为了避免嵌入NUL,并且是字节顺序不可知论者。