c#解码器如何知道它应该用于一个字符的确切字节数?

How does c# decoder know the exact number of bytes it should use for one char?

例如,一个流有四个字节:D8 00 DC 05。解码器(例如 System.Text.Decoder)如何知道应该将它们视为一个字符 \uD800\udc05 或两个单独的字符 \uD800\udc05?谢谢

可能我没有描述清楚我的问题。我的初衷是了解 UTF8 解码器如何知道它应该用于一个字符的确切字节数,因为一个 UTF8 字符可以占用一到四个字节以及处理此变量的方式是魔术。 UTF16 解码器对于代理对没有这个问题。上面的例子不适合我的问题。

.NET Framework source code,你可以看看

System.Text.Decoder 的源代码放置在 here。所以你可以在这里找到你想知道的关于你的问题的一切。

您的问题实际上是关于 UTF-16 代理对.

两个代码单元 U+D800 和 U+DC05 始终代表代理对。这两个代码单元组合成一个单独的代码点,即一个字符。

C# 调用代码单元 char 这可能有点误导,因为它有时需要两个 char 值(一对代理项)来创建一个 "character",正如您所注意到了。

U+D800 和 U+DBFF 之间的任何代码单元 (char) 值始终表示代理项对的 lower 部分,而 U 之间的任何代码单元+DC00 和 U+DFFF 是对应的 upper 部分。

该域之外的代码单元,即 U+0000 到 U+D7FF 或 U+E000 到 U+FFFF 代表它们自己,因此在这些范围内,一个 UTF-16 代码单元对应一个 Unicode 代码点.


编辑:问题改为询问 UTF-8

我将使用单词 octet 来表示正好 8 位的单词(所以八位组就是大多数人所说的 byte) .

在 UTF-8 中,您可以从八位组中第一个 0 位的位置看出该八位组在 UTF-8 序列中的位置。

  • 0xxxxxxx:如果第一位为0,则此八位字节构成一个1-八位字节序列(ASCII值)
  • 10xxxxxx:如果八位字节开始于10,这是一个连续八位字节,即不是序列中的初始
  • 110xxxxx:这是2八位字节序列
  • 中的初始八位字节
  • 1110xxxx:这是3八位字节序列
  • 中的初始八位字节
  • 11110xxx:这是4八位字节序列
  • 中的初始八位字节

由于现代 UTF-8 不允许 5 个或更长的八位字节序列,一个八位字节以五个 1 开头是非法的,11111xxx。但在早期版本中,上述方案将扩展为允许 5 个八位字节和 6 个八位字节序列(有时也更长)。


比较 UTF-16 和 UTF-8 时,请注意,UTF-16 中只需要一个 16 位代码单元的代码点与可以使用 1-、2-、或 UTF-8 中的 3 个八位字节序列。虽然在 UTF-16 中需要代理对的代码点(即两个 UTF-16 代码单元)与在 UTF-8 中需要 4 个八位字节序列的代码点完全对应。