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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在UTF-16中,UTF-16BE,UTF-16LE,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?这是一个字符串和机器字节序之间关系的帖子。
答案

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

可以从作者或文件读者的角度来看待计算机字节序的影响。

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

这并不意味着格式不灵活。对于“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时,如果没有更高级别的协议, UTF-16编码方案的字节顺序是big-endian。“

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

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

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

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

"Should UTF-16 be considered harmful?"

另一答案

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

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

另一答案

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开始字符串来表示:

  • 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数据)。

以上是关于在UTF-16中,UTF-16BE,UTF-16LE,UTF-16的端点是计算机的字节序吗?的主要内容,如果未能解决你的问题,请参考以下文章

无法读取 UTF-16 文件

linuxc把utf-16be解码成汉字怎么做

JAVA 中汉字在不同编码下的字节不同

C++处理UTF8编码的字符串

关于Unicode

UTF16和UTF8啥区别?