Mik*_*ski 5 .net c# utf-8 utf-16 character-encoding
确定对给定数量的 UTF-16 代码单元进行编码所需的最大 UTF-8 字节数(即String.LengthC# / .NET 中的值)的公式是什么?
我看到三种可能性:
# of UTF-16 code units x 2
# of UTF-16 code units x 3
# of UTF-16 code units x 4
UTF-16 代码点由 1 个或 2 个代码单元表示,因此我们只需要考虑字符串填充其中一个或另一个的最坏情况。如果 UTF-16 字符串完全由 2 个代码单元代码点组成,那么我们知道 UTF-8 表示的大小最多相同,因为代码点在两种表示中最多占用 4 个字节,因此最坏的情况就是上面的选项(1)。
因此,需要考虑的一个有趣的情况(我不知道答案)是单个代码单元 UTF-16 代码点在 UTF-8 表示中可能需要的最大字节数。
如果所有单个代码单元 UTF-16 代码点都可以用 3 个 UTF-8 字节表示(我的直觉告诉我这是最有意义的),那么选项 (2) 将是最坏的情况。如果有任何需要 4 个字节,则选项 (3) 将是答案。
有人知道哪个是正确的吗?我真的希望(1)或(2)因为(3)会让事情变得更加困难:/
更新
据我所知,UTF-16 以单个代码单元对 BMP 中的所有字符进行编码,而所有其他平面以 2 个代码单元进行编码。
看来UTF-8可以在3个字节内编码整个BMP,并使用4个字节来编码其他平面。
因此,在我看来,上面的选项(2)是正确的答案,这应该有效:
string str = "Some string";
int maxUtf8EncodedSize = str.Length * 3;
Run Code Online (Sandbox Code Playgroud)
看起来是这样检查出来的吗?
正确形成的 UTF-8 每个 Unicode 代码点最多可以有 4 个字节。
UTF-16 编码字符每个 Unicode 代码点最多可以有 2 个 16 位序列。
基本多语言平面之外的字符(包括表情符号和添加到最新版本 Unicode 中的语言)最多用 21 位表示,在 UTF-8 格式中会产生 4 个字节序列,结果也占用 4 个字节。 UTF-16 格式的字节。
然而,有些环境的行为会很奇怪。由于基本多语言平面之外的 UTF-16 字符最多需要 2 个 16 位序列(它们是可检测的,因为它们始终是 U+D800 到 U+DFFF 范围内的 16 位序列),因此一些错误的 UTF-8 实现,通常称为 CESU-8,它将这些 UTF-8 序列转换为两个 3 字节的 UTF-8 序列,每个 UTF-32 代码点总共有 6 个字节。(我相信一些早期的 Oracle DB 实现做到了这一点,而且我确信它们不是唯一的)。
还有一个小问题,即某些字形被归类为组合字符,并且在确定屏幕上显示的内容时使用多个 UTF-16(或 UTF-32)序列,但我认为这并不适用在你的情况下。
根据您的编辑,您似乎正在尝试估计 .Net 编码转换的最大长度。字符串长度测量字符总数,即 UTF-16 代码点的计数。因此,作为最坏情况的估计,我相信您可以安全地估计 count(Char) * 3,因为非 BMP 字符将是 count(Char) * 2,产生 4 个字节作为 UTF-8。
如果你想获得所表示的 UTF-32 代码点的总数,你应该能够执行类似的操作
var maximumUtf8Bytes = System.Globalization.StringInfo(myString).LengthInTextElements * 4;
Run Code Online (Sandbox Code Playgroud)
(我的 C# 有点生疏,因为过去几年我没有太多使用 .Net 环境,但我认为这可以解决问题)。