2

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

我也知道有标签,如

"meta charset="utf-8""

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

4

2 回答 2

3

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

例如,只是为了显示一些定义:

RFC 2046 , MIME 规范的第4.1.2节说:

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

RFC 2616 , HTTP 协议规范的第3.7.1节说:

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

后来被RFC 7231逆转,附录 B

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

RFC 3023 XML媒体类型规范的第3.1、3.3、3.68.5说:

与 [RFC2046] 一致,如果接收到的 text/xml 实体省略了 charset 参数,则 MIME 处理器和 XML 处理器必须使用“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 参数的处理方式与第 3.1 节中描述的 text/xml 相同。

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

...

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

此示例显示 text/xml 省略了 charset 参数。在这种情况下,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”。

JSON 规范的RFC 71598.111节说:

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

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

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

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

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

XML 1.0 规范附录 F还定义了一种算法,可以轻松确定 XML 序言使用的字符集,因此您可以读取其属性Encoding(如果存在)来确定剩余 XML 的字符集。

于 2017-06-07T20:39:16.377 回答
2

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

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

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

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

于 2017-06-05T00:56:48.363 回答