XML的默认编码是UTF-8还是UTF-16?

19

OpenTag FAQ指出:

如果XML文档中没有编码声明(并且没有可用的外部编码声明机制,如HTTP头),则XML文档的假定编码取决于字节顺序标记(BOM)是否存在。

BOM是Unicode专用标记,放置在文件顶部,指示其编码方式。UTF-8对于BOM是可选的。

First bytes        Encoding assumed
-----------------------------------------
EF BB BF           UTF-8
FE FF              UTF-16 (big-endian)
FF FE              UTF-16 (little-endian)
00 00 FE FF        UTF-32 (big-endian)
FF FE 00 00        UTF-32 (little-endian)
None of the above  UTF-8
有没有一个简单易懂的解释来说明上面这段话的意思?

4
您要寻找的解释在该段落下面的表格中。 - deceze
@deceze 当然我也读了那部分!但是我不能把表格复制粘贴到问题中,对吧? - Pacerier
1
我把表格复制粘贴到了你的问题中。:o) - deceze
你的问题是什么? - Michael Kay
当然,这个问题不是关于XSLT的问题。 - Dimitre Novatchev
值得注意的是,这不仅在OpenTag FAQ中指定,而且在XML标准中也有说明:4.3.3实体中的字符编码。在那里,它似乎只需要支持UTF-8和UTF-16自动检测编码,而这个问题中的表格还提到了UTF-32。 - Joshua Taylor
1个回答

35

你必须使用类似以下的一行代码:

<?xml version="1.0" encoding="iso-8859-1" ?>

为了指定使用哪种编码,如果未指定编码,则可以存在字节顺序标记(BOM)。如果UTF-16或UTF-32的BOM存在,则使用该编码。否则,使用UTF-8编码。(UTF-8的BOM是可选的) 编辑 BOM是一个不可见字符。但是没有必要看到它。应用程序会自动处理它。当您使用Windows记事本时,可以在保存文件时选择编码。记事本将自动在文件开头插入BOM。当您稍后重新打开文件时,记事本将识别BOM并使用适当的编码读取文件。如果您修改BOM,则没有必要这样做,因为字符可能会有不同的含义,因此文本将不同。
我将尝试用一个例子来解释。考虑一个文本文件,只包含字符“test”。默认记事本将使用ANSI编码,在十六进制模式下查看文本文件如下:
C:\>C:\gnuwin32\bin\hexdump -C test-ansi.txt
00000000  74 65 73 74                                       |test|
00000004

(正如您所看到的,我正在使用gnuwin32中的hexdump,但您也可以使用类似于Frhed的十六进制编辑器来查看它。)

这个文件前面没有BOM。这是不可能的,因为用于BOM的字符在ANSI编码中不存在。(因为没有BOM,不支持ANSI编码的编辑器将把这个文件视为UTF-8)。

现在,当我将文件保存为UTF8时,您将在“test”前面看到3个额外的字节(即BOM):

C:\>C:\gnuwin32\bin\hexdump -C test-utf8.txt
00000000  ef bb bf 74 65 73 74                              |test|
00000007

如果您使用不支持UTF-8的文本编辑器打开此文件,您实际上会看到这些字符""。

Notepad也可以将文件保存为Unicode,这意味着UTF-16小端(UTF-16LE):

C:\>C:\gnuwin32\bin\hexdump -C test-unicode.txt
00000000  ff fe 74 00 65 00 73 00  74 00                    |ÿþt.e.s.t.|
0000000a

以下是以Unicode(大端)(UTF-16BE)保存的版本:

C:\>C:\gnuwin32\bin\hexdump -C test-unicode-big-endian.txt
00000000  fe ff 00 74 00 65 00 73  00 74                    |þÿ.t.e.s.t|
0000000a

现在考虑一个包含4个中文字符“琀攀猀琀”的文本文件。当我将其保存为Unicode(大端序)时,结果如下:

C:\>C:\gnuwin32\bin\hexdump -C test2-unicode-big-endian.txt
00000000  fe ff 74 00 65 00 73 00  74 00                    |þÿt.e.s.t.|
0000000a

正如你所看到的,在UTF-16LE编码中,“test”这个单词的存储方式与UTF-16BE编码中“琀攀猀琀”这个单词的存储方式相同。但是由于字节序标记(BOM)的不同,你可以确定文件是否包含“test”或“琀攀猀琀”。如果没有BOM,你就必须猜测。

如果我理解维基百科的文章有误,它是指第一个字符“<”的编码决定了一切,对吗? - Pacerier
1
不,第一个<前面有一个看不见的额外字符。该字符以一种永远不会被误解的方式选择。因此,如果您使用十六进制编辑器查看文件,则将看到代码,并且可以确定文件的其余部分使用的编码。 - wimh
@Wimmel:BOM 不是必需的,所以你之前的评论并不完全正确。 - Dimitre Novatchev
@Wimmel。但是我们如何更改这个“不可见的额外字符”呢?我经常使用记事本..那么这是否意味着没有这样的BOM? - Pacerier
@Wimmel 很酷,太棒了。顺便问一下:如果我将 fe ff 编辑为无法识别的 BOM,比如 ab cd,那么现在如果我打开文件,他会认为它是 ASCII 编码吗? - Pacerier
显示剩余2条评论

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