为什么 UTF-8 字符串没有字节顺序问题?
Why is there no byte-order issue with UTF-8 strings?
这个问题与 this one 高度相关,但我将以一种截然不同的方式来表述它,因为我无法编辑提到的问题。
有人说,在UTF-8编码的字符串中,BOM是冗余的,因为UTF-8是一个"byte-oriented",其中最小的编码单元是一个字节,你总能从字节的最高有效位,无论它代表一个字符本身还是只是字符表示的一部分。 The Google JavaScript style guide 要求以不带 BOM 的 UTF-8 编码保存文件,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 很重要编码? IE。如果我知道编码是 UTF-16 并且我寻址字节 15,我就会知道它是字符串中第 8 个代码单元的第一个字节,我需要获取第二个字节才能找到字符或此代码单元表示的代理对的一部分。
所以谁能告诉我哪里错了?我很确定,我对字节序 and/or 计算机硬件有一些误解,所以如果有人对此进行解释或提供更多信息的链接,我将不胜感激。
更新:
所以,如果有一个 UTF-16 字符串,假设 abcdefgh 它可以以某种方式存储在内存中 a0b0c0d0e0f0g0h0 或 0a0b0c0d0e0f0g0h(每交换两个字节,顺便说一下,我也不明白,为什么是两个而不是四个)。如果一个人在一台具有相反端序的机器上读取这个字符串,即使一次一个字节,他仍然需要交换字节。
现在,如果存在相同的 UTF-8 字符串 abcdefgh,它会以某种方式存储为字节序列。问题是为什么在这种情况下不交换字节?或者,如果他们这样做了,为什么人们不需要在阅读时交换它们呢?因为,据我了解,对于这个级别的硬件和软件来说,编码之间没有区别,这只是一个字节序列。那么 UTF-16 中的字节如何交换而 UTF-8 中的字节不交换?
我故意使用 abcdefg 来表明可能存在(这不是真的,我知道我错了,但我不明白为什么)一个问题即使是这些简单的字符,也需要一个字节来编码。 AFAIK,在 UTF-8 中,人们总是可以通过寻找字节中最高有效位的其他字符来区分 a、b、c 等。 IE。如果他正在寻址字节 13(从 1 开始)并且它是 01100001 它肯定是 a 字符。不知道在此之前的字符串中有多少个字符,但这是 a 而不是其他字符编码的一部分这一事实很清楚。现在假设我一次读取 4 个字节,它们的值为 a、b、c、d。我怎么知道预定的顺序?
32 位字 -> "dcbahgfe":您可以这样看,但大多数处理器可以八位字节访问内存(术语是:内存是字节可寻址的)。因此,如果您有一个字节序列的打包数据结构,它们将具有顺序地址。
如果您读写单词并将它们视为更大的整数,那么您必须按特定顺序打包字节,但这不是字节顺序问题,而是该级别的算术问题。
就对齐而言,这取决于编译器和堆库。许多将在结构之间填充,以便每个结构都从有效的地址边界开始。
你必须意识到机器处理 UTF-8 或 UTF-16 的字节顺序 根本无关紧要 来回答为什么没有字节顺序问题使用 UTF-8。重要的是 UTF-8 和 UTF-16 是 字节流 。 UTF-8 基于 8 位代码单元,因此只有一种格式化字节流的方法:简单地一个字节接一个字节地放置。另一方面,UTF-16 基于 16 位代码单元。有两种方法可以在字节流中对 16 位值进行编码:最高有效字节优先(big endian)或最低有效字节优先(little endian)。这就是为什么有两种类型的 UTF-16 字节流,通常称为 UTF-16-BE 和 UTF-16-LE。
实际计算机在处理 UTF-8 时如何寻址、读取和写入内存是一个完全不相关的问题。计算机可能会使用奇怪的寻址方案,使 UTF-8 处理复杂化,需要字节交换或其他任何方式。因此可能存在与特定体系结构相关的字节顺序问题,但这些不是与 UTF-8 规范相关的字节顺序问题。一个实现可以确保 UTF-8 字节流的格式只有一种方式。
这个问题与 this one 高度相关,但我将以一种截然不同的方式来表述它,因为我无法编辑提到的问题。
有人说,在UTF-8编码的字符串中,BOM是冗余的,因为UTF-8是一个"byte-oriented",其中最小的编码单元是一个字节,你总能从字节的最高有效位,无论它代表一个字符本身还是只是字符表示的一部分。 The Google JavaScript style guide 要求以不带 BOM 的 UTF-8 编码保存文件,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 很重要编码? IE。如果我知道编码是 UTF-16 并且我寻址字节 15,我就会知道它是字符串中第 8 个代码单元的第一个字节,我需要获取第二个字节才能找到字符或此代码单元表示的代理对的一部分。
所以谁能告诉我哪里错了?我很确定,我对字节序 and/or 计算机硬件有一些误解,所以如果有人对此进行解释或提供更多信息的链接,我将不胜感激。
更新:
所以,如果有一个 UTF-16 字符串,假设 abcdefgh 它可以以某种方式存储在内存中 a0b0c0d0e0f0g0h0 或 0a0b0c0d0e0f0g0h(每交换两个字节,顺便说一下,我也不明白,为什么是两个而不是四个)。如果一个人在一台具有相反端序的机器上读取这个字符串,即使一次一个字节,他仍然需要交换字节。
现在,如果存在相同的 UTF-8 字符串 abcdefgh,它会以某种方式存储为字节序列。问题是为什么在这种情况下不交换字节?或者,如果他们这样做了,为什么人们不需要在阅读时交换它们呢?因为,据我了解,对于这个级别的硬件和软件来说,编码之间没有区别,这只是一个字节序列。那么 UTF-16 中的字节如何交换而 UTF-8 中的字节不交换?
我故意使用 abcdefg 来表明可能存在(这不是真的,我知道我错了,但我不明白为什么)一个问题即使是这些简单的字符,也需要一个字节来编码。 AFAIK,在 UTF-8 中,人们总是可以通过寻找字节中最高有效位的其他字符来区分 a、b、c 等。 IE。如果他正在寻址字节 13(从 1 开始)并且它是 01100001 它肯定是 a 字符。不知道在此之前的字符串中有多少个字符,但这是 a 而不是其他字符编码的一部分这一事实很清楚。现在假设我一次读取 4 个字节,它们的值为 a、b、c、d。我怎么知道预定的顺序?
32 位字 -> "dcbahgfe":您可以这样看,但大多数处理器可以八位字节访问内存(术语是:内存是字节可寻址的)。因此,如果您有一个字节序列的打包数据结构,它们将具有顺序地址。
如果您读写单词并将它们视为更大的整数,那么您必须按特定顺序打包字节,但这不是字节顺序问题,而是该级别的算术问题。
就对齐而言,这取决于编译器和堆库。许多将在结构之间填充,以便每个结构都从有效的地址边界开始。
你必须意识到机器处理 UTF-8 或 UTF-16 的字节顺序 根本无关紧要 来回答为什么没有字节顺序问题使用 UTF-8。重要的是 UTF-8 和 UTF-16 是 字节流 。 UTF-8 基于 8 位代码单元,因此只有一种格式化字节流的方法:简单地一个字节接一个字节地放置。另一方面,UTF-16 基于 16 位代码单元。有两种方法可以在字节流中对 16 位值进行编码:最高有效字节优先(big endian)或最低有效字节优先(little endian)。这就是为什么有两种类型的 UTF-16 字节流,通常称为 UTF-16-BE 和 UTF-16-LE。
实际计算机在处理 UTF-8 时如何寻址、读取和写入内存是一个完全不相关的问题。计算机可能会使用奇怪的寻址方案,使 UTF-8 处理复杂化,需要字节交换或其他任何方式。因此可能存在与特定体系结构相关的字节顺序问题,但这些不是与 UTF-8 规范相关的字节顺序问题。一个实现可以确保 UTF-8 字节流的格式只有一种方式。