关于unicode:为什么UTF-8字符串没有字节顺序问题?

Why is there no byte-order issue with UTF-8 strings?

这个问题与这个问题高度相关,但是由于我无法编辑提到的问题,因此我将以一种非常不同的方式来表达它。

有一种说法是,BOM在UTF-8编码的字符串中是多余的,因为UTF-8是"面向字节的",其中最小的代码单位是一个字节,并且您始终可以从字节,无论它是单独表示字符还是仅表示字符的一部分。 Google JavaScript样式指南要求以UTF-8编码保存文件而无BOM,Jukka Korpela的" Unicode Explained"也指出:

In UTF-8, there is no byte order issue, since the code unit size is one octet. Therefore, using BOM serves no purpose.

假设有一个仅由ASCII字符组成的UTF-8字符串,假设为" abcdefgh"。如果我将其存储在另一字节序的计算机上(使用32位字),则不会将其更改为" dcbahgfe",因为此处的一个字符为一个字节,并且其顺序相反(以相反的顺序存储) )在相反字节序的机器上?

如果不是这种情况,并且字节顺序在内存中始终相同,而仅在一个字中不同(在处理过程中),那么字节顺序为什么对UTF-16编码很重要?即如果我知道编码是UTF-16并且我寻址字节15,我会知道它是字符串中第8个代码单元的第一个字节,我需要获取第二个才能找到字符或此代码单元代表的代理对的一部分。

有人能告诉我我错了吗?我很确定,我对字节序和/或计算机硬件有一些误解,因此,如果有人对此进行解释或提供更多信息的链接,我将不胜感激。

更新:

因此,如果有UTF-16字符串,假设abcdefgh,它可以以某种方式存储在内存中a0b0c0d0e0f0g0h0或0a0b0c0d0e0f0g0h(每两个字节交换一次,这使我不明白其中一个,为什么两个而不是四个)。而且,如果人们在一台字节序相反的机器上读取该字符串,即使一次只读取一个字节,他仍然需要交换字节。

现在,如果存在相同的UTF-8字符串abcdefgh,它将以某种方式存储为字节序列。问题是为什么在这种情况下不交换字节?或者,如果这样做了,为什么在阅读它们时不需要交换它们呢?因为据我所知,就这一级别的硬件和软件而言,编码之间没有区别,这只是一个字节序列。那么,如何交换UTF-16中的字节而不会交换UTF-8中的字节呢?

我故意使用abcdefg来表明即使使用这些简单字符(需要一个字节进行编码)也可能会出现问题(这不是真的,我知道我错了,但我不明白为什么)。 AFAIK在UTF-8中始终可以从其他字符中分辨出a,b,c等,以寻找字节中的最高有效位。即如果他正在寻址字节13(从1开始)并且它是01100001,则肯定是一个字符。不知道在此字符串之前的字符串中有多少个字符,但是很明显,这是字符a而不是其他字符编码的一部分。现在假设我一次读取4个字节,它们的值分别是a,b,c,d。我怎么知道预定的订单?


您必须认识到,处理UTF-8或UTF-16的机器的字节顺序根本无济于事,无法回答为什么UTF-8没有字节顺序问题。重要的是UTF-8和UTF-16是字节流。 UTF-8基于8位代码单元,因此只有一种格式化字节流的方法:只需将一个字节放在另一个字节之后即可。另一方面,UTF-16是基于16位代码单元的。有两种方法可以在字节流中对16位值进行编码:最高有效字节在前(大字节序)或最低有效字节在前(小字节序)。这就是为什么有两种类型的UTF-16字节流,通常称为UTF-16-BE和UTF-16-LE。

在处理UTF-8时,实际的计算机如何寻址,读取和写入内存是一个完全不相关的问题。计算机可能使用奇怪的寻址方案,这会使UTF-8处理变得复杂,需要字节交换或其他操作。因此,可能存在与特定体系结构有关的字节顺序问题,但这些不是与UTF-8规范有关的字节顺序问题。一个实现可以确保只有一种方式格式化UTF-8字节流。


32位字->" dcbahgfe":您可以用这种方式查看它,但是大多数处理器可以八位字节访问内存(术语是:内存是字节可寻址的)。因此,如果您具有字节序列的打包数据结构,则它们将具有顺序地址。

如果您读写单词并将其视为更大的整数,则必须按特定顺序打包字节,但这不是字节序问题,这是该级别的算术运算。

就对齐方式而言,取决于编译器和堆库。许多将在结构之间填充,以使每个结构都从有效的地址边界开始。