【问题标题】:Why is it that UTF-8 encoding is used when interacting with a UNIX/Linux environment?为什么在与 UNIX/Linux 环境交互时使用 UTF-8 编码?
【发布时间】:2008-10-02 20:31:03
【问题描述】:

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

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

【问题讨论】:

    标签: linux unix encoding


    【解决方案1】:

    部分是因为文件系统需要 NUL ('\0') 字节来终止文件名,所以 UTF-16 不能正常工作。您必须修改大量代码才能进行更改。

    【讨论】:

    • Windows 通过制作整个 Windows API 的复制版本来增加对 UTF-16 的支持。添加对 UTF-8 的支持会简单得多。
    • 实际上 Windows 通过这样做添加了对UCS-2 的支持,然后当它证明 16 位还不够时,它是“640k 重新来过”...... ;-)
    • @dan04 使用 UTF-8 而不是 UCS2 编写 NT 会很困难,因为 NT 早于 UTF-8。这需要非凡的远见。
    • 还有,'/'(Unix 路径分隔符)。 UTF-8 最初称为文件系统安全通用字符集转换格式 (FSS-UTF)
    【解决方案2】:

    正如 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。

    【讨论】:

    • 如果应该避免使用 UCS-2,那么也应该避免使用 MS Windows :)
    • 显然 Windows 确实支持代理对,这与 UCS2 不同。
    【解决方案3】:

    我相信这主要是 UTF8 与 ASCII 的向后兼容性。

    要回答“危险”问题,您需要具体说明“互动”的含义。您的意思是与 shell、libc 还是与内核进行交互?

    【讨论】:

      【解决方案4】:

      现代 Unix 使用 UTF-8,但这并不总是正确的。在只有几年历史的 RHEL2 上,默认值为

      $ 语言环境
      朗=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 结尾的字节序列。

      【讨论】:

      • 它不一定是与 ASCII 兼容的编码,但 POSIX 标准确实说“所有位为零的字节应被解释为与移位状态无关的空字符。因此一个字节与在字符的第二个或后续字节中永远不会出现所有位零。”这意味着 UTF-16 和 UTF-32 是不允许的,但 UTF-8 是允许的。
      【解决方案5】:

      我相信当微软开始使用两字节编码时,0xffff 以上的字符并没有被分配,所以使用两字节编码意味着没有人担心字符长度不同。

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

      【讨论】:

      • 在NT设计的时候还没有UTF-8。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        我认为 7 位 ASCII 很好。

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

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

        【讨论】:

        • 我没有看到宽度更简单。您仍然必须扫描整个字符串。如果您要处理大量 CJK 文本,那么 UTF-16 实际上可以比 UTF-8 更紧凑,因此可能值得使用,否则我会在任何地方都坚持使用 UTF-8。
        • 对,UTF-16 已经失去了 UCS-2 的巨大优势。
        • (UTF-16 失去了 UCS-2 的巨大优势)……但获得了全系列的 Unicode 字符。
        【解决方案8】:

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

        【讨论】:

          猜你喜欢
          • 2017-10-08
          • 1970-01-01
          • 2016-04-06
          • 2019-03-31
          • 1970-01-01
          • 2011-04-10
          • 2011-08-17
          • 2011-10-11
          • 1970-01-01
          相关资源
          最近更新 更多