在UTF-16中,UTF-16BE,UTF-16LE,UTF-16的端点是计算机的字节序?

时间:2016-04-11 13:24:17

标签: c unicode endianness utf-16

UTF-16是一种双字节字符编码。交换两个字节'地址将产生UTF-16BE和UTF-16LE。

但我发现Ubuntu gedit文本编辑器中存在名称UTF-16编码,以及UTF-16BE和UTF-16LE。使用C测试程序,我发现我的计算机是小端,UTF-16被确认为UTF-16LE的相同编码。

另外:在小/大端计算机中有两个字节顺序的值(例如整数)。小端计算机将在硬件中产生很少的字节序值(除了Java生成的值,它总是形成一个大端)。

虽然文本可以在我的小端计算机中保存为UTF-16LE和UTF-16BE,但是字符是一个字节一个字节生成的(例如ASCII字符串,参考[3]和UTF的字节顺序 - 16只是由人类定义 - 不是因为大端机器写大端UTF-16而小端机器写小端UTF-16的现象?

  1. http://www.ibm.com/developerworks/aix/library/au-endianc/
  2. http://teaching.idallen.com/cst8281/10w/notes/110_byte_order_endian.html
  3. ASCII strings and endianness
  4. Is it true that endianness only affects the memory layout of numbers,but not string?这是字符串和机器字节序之间关系的一个帖子。

3 个答案:

答案 0 :(得分:5)

“UTF-16的结尾是计算机的字节序吗?”

可以从文件的 writer reader 的角度来看待计算机字节序的影响。

如果您正在以标准格式阅读文件,那么阅读它的机器应该无关紧要。格式应该足够明确,无论读取机器的字节顺序是什么,数据仍然可以正确读取。

这并不意味着格式不灵活。使用“UTF-16”(当格式名称中未使用“BE”或“LE”歧义消除时),该定义允许将文件标记为 大端或小端。这是通过文件的前两个字节中的“字节顺序标记”(BOM)来完成的:

https://en.wikipedia.org/wiki/Byte_order_mark

BOM的存在为文件的编写者提供了选项。他们可能会选择为内存中的缓冲区写出最自然的字节序,并包含匹配的BOM。对于其他读者来说,这不一定是最有效的格式。但任何声称支持UTF-16的程序都应该能够处理它。

是的 - 计算机的字节序可能会影响BOM标记的UTF-16文件的字节序选择。仍然...一个小端程序完全能够保存文件,标记为“UTF-16”并让它成为大端。只要BOM与数据一致,无论哪种机器写入或读取它都无关紧要。

...如果没有BOM会怎样?

这是事情变得有点朦胧的地方。

一方面,Unicode RFC 2781和Unicode FAQ很清楚。他们说,“UTF-16”格式的文件既不是0xFF 0xFE也不是0xFE 0xFF,而是interpreted as big endian

  

默认情况下,未标记的表单使用大端字节序列化,但可能在开头包含一个字节顺序标记,以指示使用的实际字节序列化。

但是要知道你是否有没有BOM的UTF-16-LE,UTF-16-BE或UTF-16文件...你需要文件外的元数据告诉你它们中的哪一个。因为并不总是放置数据的地方,所以一些程序使用启发式算法。

考虑类似this from Raymond Chen (2007)的内容:

  

您可能认为生成没有BOM的UTF-16文件的程序已损坏,但这并不意味着它们不存在。例如,

cmd /u /c dir >results.txt
     

这会生成一个没有BOM的UTF-16LE文件。

这是一个有效的UTF-16LE文件,但存储“UTF-16LE”元标签的位置在哪里?有人通过称之为UTF-16文件来传递这种情况的几率是多少?

根据经验,该术语有警告。维基百科page for UTF-16说:

  

如果BOM丢失,RFC 2781表示应该假设大端编码。 (实际上,由于Windows默认情况下使用little-endian顺序,许多应用程序默认情况下会假设使用little-endian编码。)

unicode.readthedocs.org说:

  

“UTF-16”和“UTF-32”编码名称不精确:根据上下文,格式或协议,它表示带有BOM标记的UTF-16和UTF-32,或UTF-16和UTF-32没有BOM的主机端。在Windows上,“UTF-16”通常表示UTF-16-LE。

此外,Byte-Order-Mark Wikipedia article说:

  

Unicode标准的条款D98(第3.10节)规定,“UTF-16编码方案可能会也可能不会以BOM开头。但是,如果没有BOM,并且没有更高级别的BOM协议,UTF-16编码方案的字节顺序是big-endian。“

     

更高级别的协议是否有效可以解释。例如,本机字节排序为little-endian的计算机本地文件可能被认为是隐式编码为UTF-16LE。因此,大端的推定被广泛忽视。

     

当互联网上可以访问这些相同的文件时,另一方面   手,没有这样的推定。搜索16位字符   在ASCII范围内或只是空格字符(U + 0020)是一种方法   确定UTF-16字节顺序。

因此,尽管标准没有歧义,但背景在实践中可能很重要。

正如@rici指出的那样,该标准现在已经存在了一段时间。不过,对声称为“UTF-16”的文件进行双重检查可能需要付费。或者甚至考虑你是否想要避免很多这些问题并接受UTF-8 ......

"Should UTF-16 be considered harmful?"

答案 1 :(得分:1)

没有。你不是看到小端计算机一直接收来自互联网的数据包,这是大端吗?

编码取决于您对内存的写入方式,而不是您的架构的编写方式。

答案 2 :(得分:1)

Unicode编码方案在Unicode standard的第3.10节中定义。该标准定义了七种编码方案:

  • 8位:UTF-8
  • 16位:UTF-16BE,UTF-16LE和UTF-16
  • 32位:UTF-32BE,UTF-32LE和UTF-32

对于16位和32位编码,这三种变体的字节顺序不同,可以是显式的,也可以通过以Byte Order Mark(BOM)字符开头的字符来表示,U + FEFF:< / p>

  • LE变体绝对是小端的;首先编码低位字节。不允许BOM,因此初始字符U + FEFF是零宽度不间断空间。
  • BE变种绝对是大端的;首先编码高位字节。与LE变体一样,不允许使用BOM,因此初始字符U + FEFF是零宽度不间断空间。
  • 没有endian标记的变体可能是big-little-endian。通常它将以定义字节序的BOM开始。如果没有BOM,则假定为big-endian编码。

如果要使用16位或32位编码方案进行数据序列化,通常建议使用带有显式BOM的未标记变体。但是,UTF-8是一种更常见的数据交换格式。

虽然UTF-8不需要字节序标记,但允许(但不推荐)使用BOM启动UTF-8编码字符串;这可以用于区分Unicode编码方案。许多Windows程序都这样做,并且在UTF-8传输开始时的U + FEFF应该被视为BOM(因此不是Unicode数据)。