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

本文关键字:字节数 字符 何知道 解码器 一个 | 更新日期: 2023-09-27 18:16:07

例如,一个流有四个字节: d800 DC 05。解码器(例如:System.Text.Decoder)知道它应该把它们当作一个字符'uD800'udc05或两个单独的字符'uD800'udc05吗?谢谢。

也许我没有把我的问题描述清楚。我最初的意图是要了解UTF8解码器如何知道它应该为一个字符使用的确切字节数,因为一个UTF8字符可以占用一到四个字节,处理这个变量的方式是神奇的。UTF16解码器对于代理对没有这个问题。上面的例子不适合我的问题。

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

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

两个代码单元 U+D800和U+DC05总是表示代理对。这两个代码单元组合成一个代码点,即一个字符。

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

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

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


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

我将使用octet来表示正好8位的字(所以一个octet就是大多数人所说的字节)。

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

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

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


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

有。net Framework源代码,可以看看。

System.Text.Decoder的源代码放在这里。所以你可以在这里找到你想知道的关于你的问题的所有信息。