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的好处
UTF-16的好处
UTF-32的好处
tch*_*ist 18
你真的应该问一个问题,而不是四个问题.但这里有答案.
根据定义,所有UTF转换都支持所有 Unicode代码点.这是你不必担心的事情.唯一的问题是,有些系统确实是UCS-2,但声称它们是UTF-16,而UCS-2在几个基本方面严重受损:
有关七种不同编程语言在内部使用的编码,请参阅上周题为"Unicode支持枪战"的 OSCON讲座中的功能支持摘要中的幻灯片7 .它变化很大.
UTF-8是逻辑Unicode代码点流的最佳序列化转换,因为没有特定的顺序:
每当我能逃脱它时,我都会使用UTF-8.
我已经给出了UTF-8的属性,所以这里有一些用于其他两个:
strlen
函数中永远使用O(N)访问,所以我不确定这是多么重要.我的印象是,我们几乎总是以顺序而非随机顺序处理我们的字符串,在这种情况下,这不再是一个问题.是的,它需要更多的内存,但从长远来看只会略有不同.这就是为什么我来谈论有一个UTF-16诅咒.唯一比UTF-16诅咒更糟的是 UCS-2诅咒.
Endianness和整个BOM都是诅咒UTF-16和UTF-32的问题.如果您使用UTF-8,您将不必担心这些.
我确实希望您在内部使用所有API的逻辑(即抽象)代码点,并担心仅针对外部交换的序列化.无论这些代码单元是8位宽还是16位宽,任何让你获得代码单元而不是代码点的东西都比它的价值要麻烦得多.您需要一个代码点接口,而不是代码单元接口.现在您的API使用代码点而不是代码单元,实际的底层表示不再重要.这一点很重要.
让我补充一点,每个人都在讨论ASCII与Unicode之间的错误.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的regex
Python 2和Python 3的奇妙库.它非常简洁,它实际上正确地将Unicode案例折叠 - 在许多其他Unicode事物中,标准re
得到了极其错误.)
记住: Unicode是不是只是个字符: Unicode是规则处理多个字符.一个人要么学习使用 Unicode,要么一个人反对它,如果一个人反对它,那么它对你不利.
它们都支持所有Unicode代码点.
它们具有不同的性能特征 - 例如,UTF-8对于ASCII字符更紧凑,而UTF-32使得更容易处理整个Unicode,包括基本多语言平面之外的值(即U + FFFF以上).由于每个字符的宽度可变,UTF-8字符串很难用于获取二进制编码中的特定字符索引 - 您已经扫描过了.除非您知道没有非BMP字符,否则UTF-16也是如此.
字节顺序确定(对于UTF-16和UTF-32)最高有效字节是第一个,最低有效字节是最后一个,反之亦然.例如,如果要以UTF-16表示U + 1234,则可以是{0x12,0x34}或{0x34,0x12}.一个字节顺序标记指示哪些ENDIANESS你处理.UTF-8没有不同的字节序,但在文件的开头看到UTF-8 BOM是一个很好的指标,它是 UTF-8.