我知道charset=
HTTP中的参数header:Content-Type
可以用来确定HTML内容的字符集。但是如果header中缺少参数Content-Type
,我怎么知道HTML内容的字符集呢?
我也知道有标签,如
"meta charset="utf-8""
在用于指定字符集的 HTML 中。但是我们只有在解析 HTML 之后才能得到那个标签,而解析 HTML 需要先知道字符集。
我知道charset=
HTTP中的参数header:Content-Type
可以用来确定HTML内容的字符集。但是如果header中缺少参数Content-Type
,我怎么知道HTML内容的字符集呢?
我也知道有标签,如
"meta charset="utf-8""
在用于指定字符集的 HTML 中。但是我们只有在解析 HTML 之后才能得到那个标签,而解析 HTML 需要先知道字符集。
在标头中没有显式charset
属性的情况下,Content-Type
通过不同传输方式发送的不同媒体类型具有不同的默认字符集。
例如,只是为了显示一些定义:
与其他一些参数值不同,charset 参数的值不区分大小写。 在没有字符集参数的情况下必须假定的默认字符集是 US-ASCII。
RFC 2616 , HTTP 协议规范的第3.7.1节说:
“charset”参数与某些媒体类型一起使用来定义数据的字符集(第 3.4 节)。当发送者没有提供明确的字符集参数时,“text”类型的媒体子类型被定义为在通过 HTTP 接收时具有“ISO-8859-1”的默认字符集值。除“ISO-8859-1”或其子集以外的字符集中的数据必须用适当的字符集值标记。有关兼容性问题,请参阅第 3.4.1 节。
已删除文本媒体类型的默认 ISO-8859-1 字符集;默认值现在是媒体类型定义所说的任何内容。同样,从 Accept-Charset 标头字段中删除了对 ISO-8859-1 的特殊处理。(第 3.1.1.3 节和第 5.3.3 节)。
RFC 3023 , XML媒体类型规范的第3.1、3.3、3.6和8.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 文本应以 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 的字符集。
您需要开始解析 HTML 才能看到<meta charset
元素是绝对正确的。
但这是标准化行为:您必须遵循一种编码嗅探算法,该算法开始处理 HTML 源代码,直到它知道编码,然后使用已知编码重新解析。显然,这会像您想象的那样施加限制,因此您应该根据Quentin 的评论查看规范,因为您需要了解很多情况。
基本上,如果内容可能是 UTF-16 (或UCS-2),您的嗅探器需要能够识别UTF-16字节顺序标记。它需要识别and为了跳过评论,或者为了识别元元素的开始,可以使用,或标签。"<!--"
"-->"
"<meta "
"<meta/"
"http-equiv"
"content"
"charset"
创作 HTML 时,您应该确保该<meta
元素尽可能早地出现在文件中,在前 1024 个字节内,最好是在文件中第一次出现任何非 ASCII 字符之前。