Unicode BOM for UTF-16LE vs UTF32-LE
似乎utf16-le和utf-32le使用的字节顺序标记之间存在歧义。特别是,考虑一个包含以下8个字节的文件:
如何判断此文件是否包含:
UTF16-LE BOM(FF FE),后跟3个空字符;或
utf32-le bom(FF FE 00 00)后跟一个空字符?
unicode bom在这里有描述:http://unicode.org/faq/utf_bom.html bom4,但是没有讨论这种模糊性。我错过什么了吗?
顾名思义,BOM只告诉你字节顺序,而不是编码。您必须首先知道编码是什么,然后可以使用BOM来确定对于多字节序列,最小字节还是最大字节是第一个。
BOM的一个幸运的副作用是,如果您不知道的话,有时您也可以使用它来猜测编码,但这不是它的设计目的,它不能代替发送正确的编码信息。
这是明确的。FF FE表示utf-16le,FF FE 00 00表示utf-32le。没有理由认为FF FE 00 00可能是utf-16le,因为utfs是为文本设计的,用户不应该在文本中使用nul字符。毕竟,上次打开十六进制编辑器并在文本文档中插入几个字节00是什么时候?^ ^ ^
- 空字符很可能是文本中编码的高阶协议的一部分。Unicode实际上并不关心文本中使用了什么代码点,U+0000和U+0041一样有效。
- 阅读一个高阶协议,这个理论与需要猜测编码的问题设置相冲突。如果你正在阅读一个协议,你就不会猜到编码。
- 换句话说,在文件的开头有一个U+0000是不可能的,但这是非常罕见的。如果这是您正在读取的数据的一种可能性,那么您不应该依赖于BOM来进行格式检测。
我也遇到过和爱德华一样的问题。我同意达斯汀的观点,通常在文本文件中不会使用空字符。
但是,我创建了一个包含所有Unicode字符的文件。我首先使用了utf-32le编码,然后是utf-32be编码、utf-16le和utf-16be编码以及utf-8编码。
当尝试将文件重新编码为utf-8时,我想将结果与已经存在的utf-8文件进行比较。因为在bom之后我的文件中的第一个字符是空字符,所以我无法成功地检测到带有utf-16le bom的文件,它显示为utf-32le bom,因为字节看起来与Edward描述的完全相同。bom fffe后面的第一个字符是0000,但是bom检测发现了bom fffe0000,因此检测到了utf-32le,而不是utf-16le,我的第一个0000字符被窃取并作为bom的一部分。
因此,不应该将空字符用作用UTF-16小尾数编码的文件的第一个字符,因为它会使UTF-16LE和UTF-32LE BOM不明确。
为了解决我的问题,我将交换第一个和第二个字符。-)
- 如果您仅仅依靠一个BOM来检测编码,那么您需要查看更多的字节,而不仅仅是BOM来解决UTF-16/32的不确定性。首先检查utf-16le,如果检测到,然后检查后面的n*2字节是否是有效的utf-16le,其中n是一个合理的数字。如果utf-16le无效,则重新开始并假定为utf-32le。U+0000应该是唯一不明确的代码点,并且文件开头不应该有很多空值。在某个时刻,必须有一个截止点,如果您仍然不能在那之前解决歧义,那么就提示用户,或者在处理过程中出现错误而失败。
- 这意味着,如果检测到一个utf-32le的bom,首先应该检查它是否真的是一个utf-16le的bom,代码点后面有一个U+0000。如果有很多词,这可能会有所帮助,可能还会检测代理。但是,如果只有一个观点词,这可能是困难的。但我同意,当检查有效的UTF-32码位时,如果它确实是一个UTF-16编码的文件,那么您可能会发现超过0x10ffff最大值的码位。无论如何,我们应该建议在UTF-16LE编码文件中始终放置另一个超过U+0000的代码点作为第一个代码点。