确定编码给定数量的UTF-16代码单元所需的最大UTF-8字节数(即C#/ .NET中String.Length
的值)的公式是什么?
我看到3种可能性:
1)# of UTF-16 code units x 2
2)# of UTF-16 code units x 3
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)会让事情变得更难:/
UPDATE
我不是UTF专家,但是从我可以收集到的信息来看,UTF-16在单个代码单元中对BMP中的所有字符进行编码,而所有其他平面都以2个代码单元进行编码。
似乎UTF-8可以在3个字节内编码整个BMP,并使用4个字节来编码其他平面。
因此在我看来上面的选项(2)是正确的答案,这应该工作:
string str = "Some string";
int maxUtf8EncodedSize = str.Length * 3;
这看起来好像结账了吗?
正确形成的UTF-8每个Unicode代码点最多可以有4个字节。
每个Unicode代码点,UTF-16编码的字符最多可包含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码点总共六个字节。 (我相信一些早期的Oracle数据库实现做到了这一点,我确信它们不是唯一的)。
事物中还有一个小扳手,即一些字形被归类为组合字符,并且在确定屏幕上显示的内容时使用多个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;
(我的C#有点生疏,因为我在过去几年里没有使用.Net环境,但我认为这样做很有效)。