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 个八位字节序列的代码点完全对应。
例如,一个流有四个字节: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 个八位字节序列的代码点完全对应。