【问题标题】:UTF-8 - contradictory definitionsUTF-8 - 矛盾的定义
【发布时间】:2020-07-08 14:06:17
【问题描述】:

我对 UTF-8 编码的理解是 UTF-8 字符的第一个字节可以携带任何一个

  1. 低 7 位 (0-6) 中的数据,高位 (7) 清除单字节 ASCII 范围代码点
  2. 低 5 位 (0-4) 中的数据,高位 7-5 = 110 表示 2 字节字符
  3. 低 4 位 (0-3) 中的数据,高位 7-4 = 1110 表示 3 字节字符
  4. 低 5 位 (0-2) 中的数据,高位 7-3 = 11110 表示 4 字节字符

注意第 7 位始终设置,这告诉 utf-8 解析器这是一个多字节字符。

这意味着 128-255 范围内的任何 unicode 代码点都必须以 2 个或更多字节编码,因为如果要以一个字节编码所需的高位在 UTF-8 中保留用于'多字节指示位'。所以例如字符 é(e-acute,它是 unicode 代码点 \u00E9,十进制 233)以 UTF-8 编码为两字节字符 \xC3A9。

here 的下表显示了代码点 \u00E9 如何以 UTF-8 编码为 \xC3A9。

但这似乎不是它在网页中的工作方式。我最近在 unicode 字符的渲染中遇到了一些矛盾的行为,在我的探索性阅读中遇到了这个:

  • “对于从 160 到 255 的值,UTF-8 与 ANSI 和 8859-1 相同。” (w3schools)

这显然与上述矛盾。

如果我在jsfiddle 中呈现这些不同的值,我会得到

因此 HTML 将 unicode code-point 呈现为 é,而不是该代码点的 UTF-8 2 字节编码。事实上,HTML 将 UTF-8 字符 \xC3A9 呈现为具有代码点 \xC3A9:

的 Hangul 音节

W3schools 有一个表,将 é 的 UTF-8 明确定义为十进制 233 (\xE9):

所以 HTML 是在渲染代码点,而不是 UTF-8 字符。

我在这里遗漏了什么吗?谁能向我解释为什么在一个所谓的 UTF-8 HTML 文档中,似乎根本没有 UTF-8 解析?

【问题讨论】:

  • w3school 的质量不高。我不会推荐它,而且无论如何我永远不会 100% 信任这个网站。句子“对于 160 到 255 的值,UTF-8 与 ANSI 和 8859-1 相同”。显然是错误的。他们将 Unicode 与 UTF-8 混淆了。顺便说一句,不要写\xC3A9:这很令人困惑,而且通常不是你想的那样(在小端架构上,比如 x86)。
  • @GiacomoCatenazzi w3school 可能是错误的,但 jsfiddle 示例显示浏览器正在渲染基于代码点的字节,而不是 utf-8 字符集。
  • UTF-8 只是网络的标准编码,用于传输文件。在内部它们只是 unicode 字符,所以是的,这些代码不是 UTF-8 字节,而是代码点。
  • 这里的问题是什么?是不是“谁能向我解释为什么在一个所谓的 UTF-8 HTML 文档中,似乎根本没有 UTF-8 解析?”您对什么行为感到惊讶,您期待什么?

标签: html unicode encoding utf-8


【解决方案1】:

您对 UTF-8 字节编码的理解是正确的。

您的 jsfiddle 示例仅使用 UTF-8 作为 HTML 文件的字节编码(因此使用了<meta charset="UTF-8"> HTML 标签),而不是作为 HTML 本身的编码。 HTML 仅使用 ASCII 字符作为其标记,但该标记可以表示 Unicode 字符。

UTF-8 是 Unicode 代码点的字节编码。它通常用于传输 Unicode 数据,例如通过 HTTP 传输的 HTML 文件。但是 HTML 本身仅根据 Unicode 代码点定义,而不是专门在 UTF-8 中定义的。网络浏览器将通过线路接收原始 UTF-8 字节,并将它们解码为 Unicode 代码点,然后在 HTML 上下文中处理它们。

HTML 实体仅处理 Unicode 代码点,而不是代码单元,例如 UTF-8 中使用的代码单元。

&#<xxx>; 格式的 HTML 实体通过其数值直接表示 Unicode 代码点。

  • é (é) 和 é (é) 分别表示十进制和十六进制格式的整数 233。 233是Unicode码点U+00E9 LATIN SMALL LETTER E WITH ACUTE的数值,用UTF-8字节编码为0xC3 0xA9

  • 쎩 (쎩) 以十六进制格式 (0xC3A9) 表示整数 50089。 50089是Unicode码点U+C3A9 HANGUL SYLLABLE SSYEOLG的数值,用UTF-8编码为字节0xEC 0x8E 0xA9

&<name>; 格式的 HTML 实体通过 HTML 定义的人类可读名称表示 Unicode 代码点。

  • é (é) 表示 Unicode 代码点 U+00E9,与 éé 相同。

【讨论】:

  • @ Remy Lebeau,对我来说,您回答中的关键语句是“网络浏览器将通过网络接收原始 UTF-8 字节并将它们解码为 Unicode 代码点”。所以渲染过程不识别 UTF-8,只是代码点?这是否意味着如果 javascript 从 AJAX 交换等接收到 UTF-8 格式的数据或标记,它必须在将内容注入 DOM 之前将其解码为代码点? - 因为这是我的经验,也是我问这个问题的原因。
  • @Nikkorian "所以渲染过程不能识别 UTF-8,只是代码点?" - 是的。 "这是否意味着如果 javascript 从 AJAX 交换等接收到 UTF-8 格式的数据或标记,它必须在将内容注入 DOM 之前将其解码为代码点?"-是的。 DOM 没有 UTF 编码的概念,只有 Unicode 本身。但是,在内存中,Javascript 和 DOM 字符串通常以 UTF-16 编码作为实现细节。
  • 反过来呢?如果我通过 AJAX 传递在 INPUT 中捕获的数据,数据是否会在代码点中,我是否必须在发送前转换为 UTF-8?
  • @Nikkorian 你不应该这样做,AJAX api 应该为你处理。但是,是的,DOM/脚本字符串必须在线上进行编码,而 UTF-8 是首选编码。
  • 谢谢 Remy - 这一切都开始变得有意义了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 2011-02-03
  • 1970-01-01
  • 2017-11-06
  • 2016-02-21
  • 1970-01-01
相关资源
最近更新 更多