【问题标题】:How can I know the character set of HTML content by HTTP headers?如何通过 HTTP 标头知道 HTML 内容的字符集?
【发布时间】:2017-11-04 18:52:06
【问题描述】:

我知道HTTP中header:Content-Type中的参数charset=可以用来判断HTML内容的字符集。但是如果Content-Type标头中缺少参数,我怎么知道HTML内容的字符集呢?

我也知道有这样的标签

"meta charset="utf-8""

在 HTML 中用于指定字符集。但是我们只有在解析HTML之后才能得到那个标签,而解析HTML需要先知道字符集。

【问题讨论】:

  • 您无需知道 HTML 的实际字符集即可解析它。您只需要知道它使用的是 8 位、16 位还是 32 位字符(8 位是最常见的),这在几个字节后很容易确定。 HTML 标记本身与 ASCII 兼容,因此一旦您知道所使用的字符宽度,就可以读取它们。然后一旦找到合适的<meta> 标签,您就会知道如何解释 HTML 标签之外的文本数据。

标签: html utf-8 character-encoding content-type character-set


【解决方案1】:

Content-Type 标头中没有明确的charset 属性的情况下,通过不同传输方式发送的不同媒体类型具有不同的默认字符集。

例如,仅显示一些定义:

RFC 2046,MIME 规范的4.1.2 部分说:

与其他一些参数值不同,charset 参数的值不区分大小写。 默认字符集(在没有字符集参数时必须假定)是 US-ASCII。

RFC 2616,HTTP 协议规范的3.7.1 部分说:

“charset”参数用于某些媒体类型来定义数据的字符集 (section 3.4)。 当发送方未提供明确的字符集参数时,“文本”类型的媒体子类型被定义为在通过 HTTP 接收时具有默认字符集值“ISO-8859-1”。除“ISO-8859-1”或其子集以外的字符集中的数据必须用适当的字符集值标记。有关兼容性问题,请参阅section 3.4.1

后来被RFC 7231Appendix B逆转:

已删除文本媒体类型的默认 ISO-8859-1 字符集;现在的默认值就是媒体类型定义所说的。同样,从 Accept-Charset 标头字段中删除了对 ISO-8859-1 的特殊处理。 (Section 3.1.1.3Section 5.3.3)。

XML 媒体类型规范的RFC 30233.13.33.68.5 部分说:

符合 [RFC2046],如果接收到的 text/xml 实体省略了 charset 参数,MIME 处理器和 XML 处理器必须使用默认的 charset 值“us-ascii”[ASCII]。在 XML MIME 实体通过 HTTP 传输的情况下,默认字符集值仍然是“us-ascii”。 (注意:此规范与 HTTP/1.1 存在不一致,由于历史原因,HTTP/1.1 使用 ISO-8859-1[ISO8859] 作为默认值。由于 XML 是一种新格式,因此应选择新的默认值以获得更好的 I18N。选择了 US-ASCII,因为它是 UTF-8 和 ISO-8859-1 的交集,并且已经被 MIME 使用。)

text/xml-external-parsed-entity 的 charset 参数的处理方式与 Section 3.1 中描述的 text/xml 相同。

以下列表适用于根据本规范定义字符集参数的顶级类型“text”下的 text/xml、text/xml-external-parsed-entity 和基于 XML 的媒体类型:

...

  • 如果不指定charset参数,默认为“us-ascii”。 HTTP 中“iso-8859-1”的默认值被显式覆盖。

此示例显示省略了 charset 参数的 text/xml。在这种情况下,MIME 和 XML 处理器必须假定字符集是“us-ascii”,这是 [RFC2046] 中指定的文本媒体类型的默认字符集值。 即使 text/xml 实体使用 HTTP 传输,“us-ascii”的默认值仍然有效。

不建议对 text/xml 省略 charset 参数。例如,即使 XML MIME 实体的内容是 UTF-16 或 UTF-8,或者 XML MIME 实体有明确的编码声明,XML 和 MIME 处理器必须假定字符集是“us-ascii”。

RFC 71598.111 部分,JSON 规范说:

JSON 文本应以 UTF-8、UTF-16 或 UTF-32 编码。默认编码为 UTF-8,以 UTF-8 编码的 JSON 文本是可互操作的,因为它们将被最大数量的实现成功读取;有许多实现无法成功读取其他编码(如 UTF-16 和 UTF-32)的文本。

实现不得在 JSON 文本的开头添加字节顺序标记。为了互操作性,解析 JSON 文本的实现可能会忽略字节顺序标记的存在,而不是将其视为错误。

注意:没有为此注册定义“charset”参数。添加一个确实对合规收件人没有影响。

因此,一般来说,如果您想知道给定资源使用的字符集,并且该字符集不是通过外部方式表达的,例如 Content-Type 标头的 charset 属性,那么您必须确定什么您正在处理的数据类型,然后根据该数据类型的规范概述确定其字符集。

在您的情况下,您正在通过 HTTP 处理 HTML,因此 RFC 2616 规则适用于您。 HTML 5 spec8.2.2.2 部分定义了一个非常详细的算法,用于在 Content-Type 标头中未指定 charset 属性时确定 HTML 的字符集。该算法首先检查是否存在 UTF BOM,如果不存在则假定 HTML 是 8 位的,并解析它以查找包含字符集或语言声明的任何 <meta> 标记。

XML 1.0 specificationAppendix F 还定义了一种算法,可以很容易地确定 XML prolog 使用的字符集,因此您可以读取它的 Encoding 属性(如果存在)来确定剩下的 XML。

【讨论】:

    【解决方案2】:

    您需要开始解析 HTML 才能看到 <meta charset 元素,这是绝对正确的。

    但这是标准化行为:您必须遵循一种编码嗅探算法,该算法开始处理 HTML 源代码,直到它知道编码,然后使用已知编码重新解析。显然,这会像您想象的那样施加限制,因此您应该检查 the specificationQuentin's comment,因为您需要注意很多情况。

    基本上,如果内容可能是 UTF-16(或 UCS-2),您的嗅探器需要能够识别 UTF-16 字节顺序标记。它需要识别"<!--""-->" 以跳过cmets,并识别"<meta ""<meta/" 以识别元元素的开头,可以使用"http-equiv""content" 或@987654332 @标签。

    在创作 HTML 时,您应该确保 <meta 元素尽可能早地出现在文件中,在前 1024 个字节内,最好在文件中第一次出现任何非 ASCII 字符之前。

    【讨论】:

      猜你喜欢
      • 2015-12-16
      • 1970-01-01
      • 2012-03-14
      • 1970-01-01
      • 2011-01-26
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多