UTF-16LE与UTF32-LE的Unicode BOM

UTF-16LE与UTF32-LE的Unicode BOM,unicode,character-encoding,utf-16,file-type,byte-order-mark,Unicode,Character Encoding,Utf 16,File Type,Byte Order Mark,UTF16-LE和UTF-32LE使用的字节顺序标记之间似乎存在歧义。特别是,考虑一个包含以下8个字节的文件: FF FE 00 00 00 00 00 00 如何判断此文件是否包含: UTF16-LE BOM(FF FE)后跟3个空字符;或 UTF32-LE BOM(FF FE 00 00)后跟一个空字符 这里描述了Unicode BOM:但没有讨论这种模糊性。我遗漏了什么吗?顾名思义,BOM表只告诉您字节顺序,而不是编码。您必须先知道编码是什么,然后才能使用BOM表确定对于多字节序列,最低

UTF16-LE和UTF-32LE使用的字节顺序标记之间似乎存在歧义。特别是,考虑一个包含以下8个字节的文件:

FF FE 00 00 00 00 00 00
如何判断此文件是否包含:

  • UTF16-LE BOM(FF FE)后跟3个空字符;或
  • UTF32-LE BOM(FF FE 00 00)后跟一个空字符

  • 这里描述了Unicode BOM:但没有讨论这种模糊性。我遗漏了什么吗?

    顾名思义,BOM表只告诉您字节顺序,而不是编码。您必须先知道编码是什么,然后才能使用BOM表确定对于多字节序列,最低或最高有效字节是第一个


    BOM的一个幸运的副作用是,如果您不知道,您有时也可以使用它来猜测编码,但这不是它的设计目的,它不能代替发送正确的编码信息。

    它是明确的
    FF FE
    表示UTF-16LE,而
    FF FE 00
    表示UTF-32LE。没有理由认为
    FF FE 00 00
    可能是UTF-16LE,因为UTF是为文本设计的,用户不应该在文本中使用NUL字符。毕竟,上次打开十六进制编辑器并在文本文档中插入几个字节的00是什么时候^_^

    我和爱德华一样经历过同样的问题。我同意Dustin的观点,通常不会在文本文件中使用空字符

    但是,我创建了一个包含所有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 little-endian编码的文件的第一个字符,因为它会使utf-16le和utf-32le BOM不明确


    为了解决我的问题,我将交换第一个和第二个字符。:-)

    空字符很可能是文本中编码的高阶协议的一部分。Unicode实际上并不关心文本中使用的代码点,而U+0000与U+0041一样有效。阅读高阶协议时,这一理论与必须猜测编码的问题设置相冲突。如果你在读一个协议,你就猜不到编码。换句话说,在一个文件的开头有一个U+0000不是不可能的,但这是非常罕见的。如果您正在读取的数据可能存在这种情况,则不应依赖BOM进行格式检测。如果仅依赖BOM进行编码检测,则需要查看更多字节,而不仅仅是BOM来解决UTF-16/32歧义。首先检查UTF-16LE,如果检测到,则检查后续N*2字节是否有效,其中N是一个合理的数字。如果UTF-16LE无效,则重新开始并假定为UTF-32LE。U+0000应该是唯一不明确的代码点,并且文件开头不应该有很多空值。在某一点上,必须有一个截止点,如果到那时你仍然无法解决歧义,则提示用户,或以错误导致处理失败。这意味着,如果检测到utf-32le BOM,则应首先检查它是否真的是一个utf-16le BOM,后面有一个U+0000代码点。如果有很多单词,这可能会有所帮助,可能还会检测到代词。但如果只有一个观点,这可能很难。但我同意,在检查有效的utf-32代码点时,如果它确实是一个utf-16编码文件,您可能会发现超出0x10FFFF最大值的代码点。无论如何,我们应该建议始终将U+0000以外的另一个代码点作为utf-16le编码文件中的第一个代码点。