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

503
8个回答

397

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


22
需要注意的一点是,ASCII 只扩展到 0 到 127。最高位始终为 0。 - Hritik
3
当定义了超过127的代码点时,编码系统是扩展ASCII的一个版本。 - Rohan Bhale
7
@RohanBhale 不要使用“扩展ASCII”这个词组,它只会引起混淆。 - Mr Lister
1
但是扩展ASCII可能是正确的术语。我在多个资源上都读到了这一点。 - Rohan Bhale
我总是听到它被称为“高ASCII”。 - user5311618
在过去30多年的MsDos、Windows、*nix和互联网中,我从未听说过“高”ASCII。它一直被称为“扩展ASCII”。 - StingyJack

160

维基百科对这两个概念都有很好的解释:UTF-8Latin-1 (ISO-8859-1)。前者是可变长度编码,而后者是单字节固定长度编码。

Latin-1仅编码Unicode字符集的前256个代码点,而UTF-8可用于编码所有代码点。在物理编码层面上,只有代码点0-127被相同地编码,代码点128-255与Latin-1相比则变成了2个字节的序列。


@mu 或许我的陈述有歧义,但并不是不正确的——我所说的并不是编码字节序列,而是字符集被编码;这意味着 ISO-8859-1 用于编码 Unicode 字符集的前 256 个代码点。 - StaxMan
1
你的澄清对我有帮助,“模棱两可”可能比“不正确”更合适。 - mu is too short

120

UTF

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

简而言之,在 7-bit-safe ASCII 字符以下的任何具有代码点/序数表示的字符都由相同的 1 字节序列表示,与大多数其他单字节编码一样。 带有代码点超过 127 的任何字符都由两个或更多字节的序列表示,其中编码的细节最好在此处解释。

ISO-8859

ISO-8859 是一系列单字节编码方案,用于表示可在 127 到 255 范围内表示的字母表。 这些各种字母表被定义为 "部分",格式为 ISO-8859-n,其中最熟悉的可能是 ISO-8859-1,也称为 'Latin-1'。 与UTF-8一样,7-bit-safe ASCII 在使用任何编码系列时都不受影响。

这种编码方案的缺点是无法容纳由超过128个符号组成的语言,或者安全地显示多个符号系列。 此外,随着 UTF 的崛起,ISO-8859 编码已经不再流行。 管理它的 ISO "工作组" 已于2004年解散,将维护工作交给其上级子委员会。

Windows代码页

值得一提的是,微软还维护着一组字符编码,与 ISO-8859 有限制的兼容性,通常表示为“cp####”。微软似乎倾向于将最新产品发布转向使用 Unicode 的某种形式,但出于遗留或互操作性原因,您仍然可能会遇到这些编码。

例如,cp1252 是 ISO-8859-1 的超集,包含附加的可打印字符在 0x80-0x9F 范围内,特别是欧元符号 和备受诟病的“智能引号” “”。这经常导致不匹配,在8859-1下显示正常的情况下,可以作为1252显示正常,但是当其中一个额外符号出现时,就会出现问题。

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


2
回答问题并提供有关相关编码的信息会得到加分。关于UTF-8的代码点,根据https://dev59.com/HWkv5IYBdhLWcg3w9lei#38488358,UTF-8支持2^21个代码点。这是一个错误吗?还是需要进行修复? - Tom Loredo
1
Unicode实际上是由17个平面组成的,每个平面都有2^16个代码点。范围从0x00_0000到0x1F_FFFF。这17个平面可以容纳1,114,112个代码点。其中,2048个是代理项,66个是非字符,137468个保留供私人使用,剩下974530个用于公共分配,约为100万个。请参阅UTF-8可以编码多少个字符? - georgeawg

39
  • 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'

27

ISO-8859-1是上世纪80年代的一种遗留标准。它只能表示256个字符,因此只适用于一些西方语言。即使对于许多支持的语言,也缺少一些字符。如果您使用这种编码创建文本文件并尝试复制/粘贴一些中文字符,则会看到奇怪的结果。换句话说,不要使用它。Unicode已经取代了ISO-8859-1成为全球通用的字符集,而UTF-8则是当今的标准,除非你有一些旧系统需要兼容(例如需要与所有东西兼容的HTTP头)。


1
我曾经看到过Umlaut不应该用UTF8转换的情况。我们看到了这方面的例子,并在搜索中发现了ISO-8859-1,它似乎可以工作。我们与许多德国科学家合作。 - Aggie Jon of 87
5
在utf8中,umlaut被表示为两个字符。它们可以成功转换并正常工作。问题出在那些期望每个字符只占用1个字节的程序上。对于这些遗留程序,ISO-8859-1提供了1个字节的umlaut。 - Erik Aronesty
2
因此,换句话说,不要使用它。我不会这么说,因为有些情况下,ISO-8859-1比UTF-8更适合,因为单个字节和256个字符足以满足需求,从而实现更快的处理速度和更少的负载。 - AndreasRu
举个单字节编码更为适用的例子,短信消息有140字节的限制,主要使用单字节编码。如果你是一个发送自动化短信消息的企业,你不想为了不使用传统标准而将成本翻倍。 - Caleb McNevin

4

还有一件重要的事情需要意识到:如果你看到 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-1windows-1252的标签,而且Web浏览器不以任何方式支持ISO 8859-1:HTML规范指出,编码规范中的所有编码必须得到支持,没有更多了。

此外,HTML数字字符引用基本上使用Windows-1252来表示8位值,而不是Unicode代码点;根据https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state…将产生U+2026而不是U+0085。


抱歉!我本来写了那个,但在重写时不小心丢失了。现在我已经加上了。 - Chris Morgan

3

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


0

我研究这个问题的原因是从兼容性的角度考虑。Latin1字符集(iso-8859)可以完全兼容存储在utf8数据存储中。所有的ascii和扩展ascii字符都将被存储为单字节。

从utf8转换到Latin1字符集可能有效,也可能无效。如果有任何2字节字符(超出扩展ascii 255),它们将无法存储在Latin1数据存储中。


2
有帮助,但我认为在扩展ASCII 255中你的意思是127而不是255? - user5066707
24
Latin-1或iso-8859-1不能完全兼容存储在utf8中。127以上的任何Latin-n或iso-8859-n字符都无法翻译为一个单字节的utf-8字符。但是,对于值1-127,它们会被准确地翻译。 - Marlin Pierce
6
这个回答在使用“扩展ASCII”这个术语时有点令人困惑,它只是指任何不是ASCII的字符编码的术语。UTF-8和Latin-1都是扩展ASCII编码的例子。但是,在UTF-8中,非ASCII Latin-1字符(即代码点大于127的字符)不能被编码为单个字节。 - rdb
在UTF-8编码中,2字节编码从128开始。然而,在两种编码中都有匹配的字符,因此可以进行ISO 8859-1 -> UTF-8 -> ISO 8859-1的无损转换,但如果UTF-8文档中有任何大于255的字符,则无法进行无损转换。 - silicontrip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接