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

use*_*860 4 unicode cpu-word endianness character-encoding

这个问题是高度相关的这一个,但我会制定它在很多不同的方式,因为我不能编辑提到的一个。

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

在 UTF-8 中,没有字节顺序问题,因为代码单元大小是一个八位字节。因此,使用 BOM 没有任何意义。

假设有一个仅由 ASCII 字符组成的 UTF-8 字符串,比如说“ abcdefgh ”。如果我将它存储在具有另一个字节序(使用 32 位字)的机器上,它不会被更改为“ dcbahgfe ”,因为这里的一个字符是一个字节,并且它们的顺序是相反的(以相反的顺序存储) ) 在具有相反字节序的机器上?

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

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


更新

所以,如果有一个 UTF-16 字符串,假设abcdefgh它可以以某种方式存储在内存a0b0c0d0e0f0g0h00a0b0c0d0e0f0g0h 中(每交换两个字节,顺便说一句,我也不明白,为什么是两个而不是四个)。如果有人在具有相反字节序的机器上读取这个字符串,即使一次一个字节,他仍然需要交换字节。

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

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

nwe*_*hof 7

您必须意识到,处理 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 字节流。