UTF-8和ISO-8859-1有什么区别?


UTF-8是一种多字节编码,可以表示任何Unicode字符。ISO 8859-1是一种单字节编码,可以表示Unicode的前256个字符。两者都以完全相同的方式编码ASCII。


维基百科解释得很好:UTF-8 vs Latin-1 (ISO-8859-1)。前者为变长编码,后者为单字节定长编码。 Latin-1只编码Unicode字符集的前256个码位,而UTF-8可用于编码所有码位。在物理编码级别,只有码点0 - 127编码相同;编码点128 - 255的不同之处在于,使用UTF-8时会变成2字节序列,而使用Latin-1时会变成单字节序列。


ISO-8859-1 is a legacy standards from back in 1980s. It can only represent 256 characters so only suitable for some languages in western world. Even for many supported languages, some characters are missing. If you create a text file in this encoding and try copy/paste some Chinese characters, you will see weird results. So in other words, don't use it. Unicode has taken over the world and UTF-8 is pretty much the standards these days unless you have some legacy reasons (like HTTP headers which needs to compatible with everything).


UTF

UTF是一组多字节编码方案,它可以表示最多2^31个[大约20亿]字符的Unicode码位。UTF-8是一种灵活的编码系统,它使用1到4个字节来表示前2^21个[大约200万个]码位。

长话短说:任何码位/序号表示低于127的字符,即7位安全ASCII,都与大多数其他单字节编码一样,由相同的1字节序列表示。任何码位大于127的字符都由两个或多个字节的序列表示,这里最好解释编码的细节。

ISO-8859

ISO-8859是一组单字节编码方案,用于表示可以在127到255范围内表示的字母。这些不同的字母被定义为ISO-8859-n格式的“部件”,其中最熟悉的可能是ISO-8859-1又名“Latin-1”。与UTF-8一样,7位安全ASCII不受使用的编码族影响。

这种编码方案的缺点是它不能适应由128个以上符号组成的语言,也不能同时安全地显示一个以上的符号族。同样,随着UTF的兴起,ISO-8859编码也不再受欢迎。负责该系统的ISO“工作组”已于2004年解散,将维护工作留给其母小组委员会。

Windows代码页

值得一提的是,微软还维护了一组与ISO-8859有有限兼容性的字符编码,通常记为“cp####”。MS似乎在推动他们最近发布的产品以一种或另一种形式使用Unicode,但是由于遗留和/或互操作性的原因,您仍然可能遇到它们。

例如,cp1252是ISO-8859-1的超集,包含0x80-0x9F范围内的额外可打印字符,特别是欧元符号€和备受诟病的“智能引号”“”。这经常会导致不匹配,8859-1可以完全正常地显示为1252,而1252似乎可以正常地显示为8859-1,但当其中一个额外的符号出现时,就会出现错误。

除了cp1252,土耳其的cp1254是类似于ISO-8859-9的超集,但所有其他Windows代码页至少有一些基本的冲突,如果不是完全不同于他们的8859等效。


我研究这个问题的原因是从这个角度,他们在什么方面是兼容的。Latin1字符集(iso-8859) 100%兼容存储在utf8数据存储中。所有ascii和扩展ascii字符将存储为单字节。

反之,从utf8到Latin1字符集可能工作,也可能不工作。如果有任何2字节字符(超出扩展ascii 255的字符),它们将不会存储在Latin1数据存储中。


从另一个角度来看,unicode和ascii编码都无法读取的文件,因为其中有一个字节0xc0,似乎可以被iso-8859-1正确读取。需要注意的是,文件中当然不应该包含unicode字符。


ASCII: 7位。128码位。 iso -8859- 1:8位。256个码位。 UTF-8: 8-32位(1-4字节)。1,112,064个代码点。

ISO-8859-1和UTF-8都与ASCII向后兼容,但UTF-8与ISO-8859-1不向后兼容:

#!/usr/bin/env python3

c = chr(0xa9)
print(c)
print(c.encode('utf-8'))
print(c.encode('iso-8859-1'))

输出:

©
b'\xc2\xa9'
b'\xa9'

还有一件重要的事情需要注意:如果你看到ISO -8859-1,它可能指的是Windows-1252,而不是ISO/IEC 8859-1。它们在0x80-0x9F范围内不同,其中ISO 8859-1具有C1控制代码,而Windows-1252具有有用的可见字符。

例如,ISO 8859-1使用0x85作为控制字符(在Unicode中,U+0085, ' '),而Windows-1252使用水平省略号(在Unicode中,U+2026水平省略号,…)。

WHATWG编码规范(如HTML所使用的)明确声明ISO -8859-1是windows-1252的标签,而web浏览器不以任何方式支持ISO 8859-1: HTML规范说编码规范中的所有编码都必须支持,仅此而已。

同样有趣的是,HTML数字字符引用基本上使用Windows-1252来表示8位值,而不是Unicode代码点;Per https://html.spec.whatwg.org/#numeric-character-reference-end-state, …会产生U+2026而不是U+0085。