什么是最好的UTF

Ahm*_*mad 11 unicode utf-8 utf

我对Unicode中的UTF感到困惑.

有UTF-8,UTF-16和UTF-32.

我的问题是:

  1. 什么UTF支持所有Unicode块?

  2. 什么是最好的UTF(性能,大小等),为什么?

  3. 这三个UTF有什么不同?

  4. 什么是字节顺序和字节顺序标记(BOM)?

谢谢

Del*_*ani 28

什么UTF支持所有Unicode块?

所有UTF编码都支持所有Unicode块 - 没有UTF编码不能代表任何Unicode代码点.但是,一些非UTF,较旧的编码,例如UCS-2(类似于UTF-16,但缺少代理对,因此缺乏编码高于65535/U + FFFF的代码点的能力),可能不会.

什么是最好的UTF(性能,大小等),为什么?

对于主要是英语和/或仅ASCII的文本数据,UTF-8是迄今为止最节省空间的.但是,UTF-8的空间效率通常低于UTF-16和UTF-32,其中大多数使用的代码点都很高(例如大型CJK文本).

这三个UTF有什么不同?

UTF-8将每个Unicode代码点编码为一到四个字节.Unicode值0到127与ASCII中的相同,编码方式与ASCII格式相同.值128到255的字节用于多字节代码点.

UTF-16以两个字节(一个UTF-16值)或四个字节(两个UTF-16值)对每个Unicode码点进行编码.基本多语言平面中的任何内容(Unicode代码点0到65535,或U + 0000到U + FFFF)都使用一个UTF-16值进行编码.来自较高平原的代码点通过称为"代理对"的技术使用两个UTF-16值.

UTF-32不是Unicode的可变长度编码; 所有Unicode代码点值都按原样编码.这意味着U+10FFFF编码为0x0010FFFF.

什么是字节顺序和字节顺序标记(BOM)?

字节顺序是一段数据,特定CPU架构或协议如何对多字节数据类型的值进行排序.Little-endian系统(例如x86-32和x86-64 CPU)将最不重要的字节放在第一位,而big-endian系统(例如ARM,PowerPC和许多网络协议)将最重要的字节放在第一位.

在小端编码或系统中,32位值0x12345678被存储或传输为0x78 0x56 0x34 0x12.在大端编码或系统中,它被存储或传输为0x12 0x34 0x56 0x78.

在UTF-16和UTF-32中使用字节顺序标记来表示文本将被解释为哪个字节序.Unicode以巧妙的方式实现这一点 - U + FEFF是一个有效的代码点,用于字节顺序标记,而U + FFFE则不是.因此,如果文件以文件开头0xFF 0xFE,则可以假定文件的其余部分以小端字节顺序存储.

UTF-8中的字节顺序标记在技术上是可行的,但由于显而易见的原因,在字节顺序的上下文中没有意义.但是,以UTF-8编码的BOM开头的流几乎肯定意味着它是UTF-8,因此可以用于识别.

UTF-8的好处

  • ASCII是UTF-8编码的子集,因此是将ASCII文本引入"Unicode世界"而不必进行数据转换的好方法
  • UTF-8文本是ASCII文本最紧凑的格式
  • 有效的UTF-8可以按字节值排序,并生成有序的代码点

UTF-16的好处

  • UTF-16比UTF-8更容易解码,即使它是可变长度编码
  • 对于BMP中的字符,UTF-16比UTF-8更节省空间,但在ASCII之外

UTF-32的好处

  • UTF-32不是可变长度的,因此它不需要特殊的逻辑来解码

  • 但是,UTF-8"BOM"用作UTF-8文本的指示符.虽然从技术上讲它不是一个BOM,但它更像是一个标记.请注意,UTF-32永远不会比UTF-8和UTF-16更节省空间.它通常不会用于交互,而是作为内部编码,因为您稍后会提到的好处. (3认同)

tch*_*ist 18

"回答我这些问题四,因为很久以前都回答了这些问题."

你真的应该问一个问题,而不是四个问题.但这里有答案.

  1. 根据定义,所有UTF转换支持所有 Unicode代码点.这是你不必担心的事情.唯一的问题是,有些系统确实是UCS-2,但声称它们是UTF-16,而UCS-2在几个基本方面严重受损:

    • UCS-2不是有效的Unicode编码.
    • UCS-2仅支持Unicode的1/6.也就是说,只有飞机0,而不是飞机1-16.
    • UCS-2允许Unicode标准保证的代码点永远不会在有效的Unicode流中.这些包括
      • 所有2,048个UTF-16代理,代码点U + D800到U + DFFF
      • U + FDD0和U + FDEF之间的32个非字符代码点
      • 在U + FFEF和U + FFFF都有哨兵

    有关七种不同编程语言在内部使用的编码,请参阅上周题为"Unicode支持枪战"的 OSCON讲座中的功能支持摘要中的幻灯片7 .它变化很大.

  2. UTF-8是逻辑Unicode代码点流的最佳序列化转换,因为没有特定的顺序:

    • UTF-8是Web上事实上的标准Unicode编码.
    • UTF-8可以存储在以null结尾的字符串中.
    • UTF-8没有令人烦恼的BOM问题.
    • UTF-8不存在UCS-2与UTF-16混淆的风险.
    • UTF-8非常有效地压缩ASCII文本,因此即使是XML或HTML的亚洲文本也经常比UTF-16更小.这是一个重要的事情要知道,因为它是一个违反直觉和令人惊讶的结果.ASCII标记标记通常弥补了额外的字节.如果你真的担心存储,你应该使用正确的文本压缩,如LZW和相关的算法.只是bzip它.
    • 如果需要,它可以被用于任意大量的跨Unicodian点.例如,使用原始UTF-8算法,64位机器上的MAXINT变为13个字节.但是,此属性非常有用,必须非常谨慎使用,以免被误认为是合法的UTF-8流.

    每当我能逃脱它时,我都会使用UTF-8.

  3. 我已经给出了UTF-8的属性,所以这里有一些用于其他两个:

    • UTF-32在内部存储方面具有独特的优势:O(1)访问代码点N.也就是说,当您需要随机访问时,可以进行恒定时间访问.记住我们在C strlen函数中永远使用O(N)访问,所以我不确定这是多么重要.我的印象是,我们几乎总是以顺序而非随机顺序处理我们的字符串,在这种情况下,这不再是一个问题.是的,它需要更多的内存,但从长远来看只会略有不同.
    • UTF-16是一种糟糕的格式,具有UTF-8和UTF-32的所有缺点,但没有任何优点.毫无疑问,如果处理得当,UTF-16当然可以使用,但这样做需要付出实际努力,而您的语言可能无法帮助您.实际上,您的语言可能会对您不利.我曾经使用UTF-16足以知道它是一种皇室般的痛苦.如果你在这个问题上可能有任何选择的话,我会清楚这些,特别是UTF-16.语言支持几乎从未出现过,因为有大量歇斯底里的鼠海豚都在争夺注意力.即使存在适当的代码点而不是代码单元访问机制,这些通常也很难使用并且很难输入,并且它们不是默认的.这很容易导致在部署之前可能无法捕获的错误; 相信我,因为我去过那里.

    这就是为什么我来谈论有一个UTF-16诅咒.唯一比UTF-16诅咒更糟UCS-2诅咒.

  4. Endianness和整个BOM都是诅咒UTF-16和UTF-32的问题.如果您使用UTF-8,您将不必担心这些.

我确实希望您在内部使用所有API的逻辑(即抽象)代码点,并担心仅针对外部交换的序列化.无论这些代码单元是8位宽还是16位宽,任何让你获得代码单元而不是代码点的东西都比它的价值要麻烦得多.您需要一个代码点接口,而不是代码单元接口.现在您的API使用代码点而不是代码单元,实际的底层表示不再重要.这一点很重要.


类别错误

让我补充一点,每个人都在讨论ASCII与Uni​​code之间的错误.Unicode是非常 "像ASCII但更多的字符."这可能描述ISO 10646,但它并没有描述的Unicode.Unicode不仅仅是一个特定的曲目,而是处理它们的规则.不仅仅是更多的角色,而是更多的角色,伴随着特殊的规则. 没有Unicode规则的Unicode字符不再是Unicode字符.

如果您使用ASCII思维模式处理Unicode文本,您将一次又一次地获得各种破坏.它不起作用.仅举一个例子,正是由于这种误解,Python模式匹配库re在不区分大小写的情况下完全做错了.如果两个代码点具有相同的小写,则它盲目地假设两个代码点计为相同.这是一种ASCII思维模式,这就是它失败的原因.你不能以这种方式对待Unicode,因为如果你这样做,你就会违反规则而不再是Unicode.这只是一团糟.

例如,Unicode将U + 03C3 GREEK SMALL LETTER SIGMA和U + 03C2 定义GREEK SMALL LETTER FINAL SIGMA为彼此不区分大小写的版本.(这称为Unicode casefolding.)但是,由于它们在盲目映射到小写并进行比较时不会更改,因此该比较失败.你不能这样做.通过将小写比较切换为大写比较,您无法在一般情况下修复它.当你需要使用casefolding时使用casemapping掩盖了对整个作品的理解.

(而且没什么:Python 2更糟糕了.我建议不要使用Python 2用于Unicode;如果你想在Python中使用Unicode,请使用Python 3.对于Pythonistas,我推荐的解决方案是Python无数的Unicode正则表达式问题的解决方案是Matthew Barnett的regexPython 2和Python 3的奇妙库.它非常简洁,它实际上正确地将Unicode案例折叠 - 在许多其他Unicode事物中,标准re得到了极其错误.)

记住: Unicode是不是只是个字符: Unicode是规则处理多个字符.一个人要么学习使用 Unicode,要么一个人反对它,如果一个人反对它,那么它对不利.


Jon*_*eet 6

  1. 它们都支持所有Unicode代码点.

  2. 它们具有不同的性能特征 - 例如,UTF-8对于ASCII字符更紧凑,而UTF-32使得更容易处理整个Unicode,包括基本多语言平面之外的值(即U + FFFF以上).由于每个字符的宽度可变,UTF-8字符串很难用于获取二进制编码中的特定字符索引 - 您已经扫描过了.除非您知道没有非BMP字符,否则UTF-16也是如此.

  3. 对于UTF-8,UTF-16UTF-32来说,查看维基百科文章可能最容易

  4. 字节顺序确定(对于UTF-16和UTF-32)最高有效字节是第一个,最低有效字节是最后一个,反之亦然.例如,如果要以UTF-16表示U + 1234,则可以是{0x12,0x34}或{0x34,0x12}.一个字节顺序标记指示哪些ENDIANESS你处理.UTF-8没有不同的字节序,但在文件的开头看到UTF-8 BOM是一个很好的指标,它 UTF-8.