C# 拉丁语、汉语、西里尔语等的子字符串UTF-8
在Windows Phone上,我希望将任何给定字符串的子字符串长度等于100个ASCII字符 长度显然是无用的,因为中文字符串每个字符使用3个字节,丹麦字符串每个字符使用2或4个字节,而俄语字符串每个字符使用4个字节 唯一可用的编码是UTF-8和UTF-16。那我该怎么办 这个想法是:C# 拉丁语、汉语、西里尔语等的子字符串UTF-8,c#,.net,utf-8,C#,.net,Utf 8,在Windows Phone上,我希望将任何给定字符串的子字符串长度等于100个ASCII字符 长度显然是无用的,因为中文字符串每个字符使用3个字节,丹麦字符串每个字符使用2或4个字节,而俄语字符串每个字符使用4个字节 唯一可用的编码是UTF-8和UTF-16。那我该怎么办 这个想法是: private static string UnicodeSubstring(string text, int length) { var bytes = Encoding.UTF8.GetBytes(
private static string UnicodeSubstring(string text, int length)
{
var bytes = Encoding.UTF8.GetBytes(text);
return Encoding.UTF8.GetString(bytes, 0, Math.Min(bytes.Length, length));
}
但是长度需要与每个字符使用的字节数正确地分开,因此最后一个字符总是正确地呈现。一个选项是简单地遍历字符串,计算每个字符的字节数 如果您知道不需要处理BMP以外的字符,这相当简单:
public string SubstringWithinUtf8Limit(string text, int byteLimit)
{
int byteCount = 0;
char[] buffer = new char[1];
for (int i = 0; i < text.Length; i++)
{
buffer[0] = text[i];
byteCount += Encoding.UTF8.GetByteCount(buffer);
if (byteCount > byteLimit)
{
// Couldn't add this character. Return its index
return text.Substring(0, i);
}
}
return text;
}
带有inutf8limit的公共字符串子字符串(字符串文本,int byteLimit)
{
int字节数=0;
char[]buffer=新字符[1];
for(int i=0;i字节限制)
{
//无法添加此字符。请返回其索引
返回text.Substring(0,i);
}
}
返回文本;
}
如果必须处理代理项对,则会变得稍微复杂一些:(一个选项是简单地添加“字符”(如果需要支持代理项对,则包括它们)查看结果字符串是否转换为所需的正确数字。一个方法是检查最后一个字符是否为正确数字,并删除一个字符,直到正确呈现为止
private static string UnicodeSubstring(string text, int length)
{
var bytes = Encoding.UTF8.GetBytes(text);
var result = Encoding.UTF8.GetString(bytes, 0, Math.Min(bytes.Length, length));
while ('\uFFFD' == result[result.Length - 1])
{
result = result.Substring(0, result.Length - 1);
}
return result;
}
虽然这是一个非常古老的问题,但我认为正确的方法是使用类的。它的主要优点是.NET文档保证
net461
及以上版本,StringInfo
保证符合Unicode标准8.0.0版:
来电人士须知
在内部,StringInfo类调用的方法
CharUnicodeInfo类确定字符的方法
类别。从.NETFramework 4.6.2开始,字符
分类基于Unicode标准8.0.0版。对于
NET Framework 4通过.NET Framework 4.6.1,它基于
Unicode标准版本6.3.0.在.NET核心中,它基于
Unicode标准,版本8.0.0
现在,如果Microsoft文档中没有关于如何调用SubstringByTextElements的示例,那么实际上如何调用SubstringByTextElements呢
在StringInfo
类中,有一个注释说明:
- 通过调用
方法来检索包含每个文本元素起始索引的数组。然后,您可以通过将这些索引传递给ParseCombiningCharacters
方法来检索单个文本元素SubstringByTextElements
你是说“相当于100字节”吗不是ASCII字符,对字符来说是无用的,因为取决于编码的可变字节数。UTF 8是一个可变长度的多字节编码。每个字符可以使用1到4字节。因此,它不能由固定的字节数分隔。如果考虑每个“完整字符”的替代对实际字节数。在UTF8中,可能比4…+1还要多。我会使用Encoding.UTF8.GetBytes(stringWithCurrentCharacterOrPair)而不是ifs…Encoding.UTF8.GetByteCount(…)也可以为每个字符调用。有趣的想法。@AlexeiLevenkov:我试图避免为每个字符创建新字符串,但使用GetByteCount我们可以重用单个数组…编辑。@JonSkeet只是好奇,知道为什么C#没有内置子字符串来处理这个问题吗?@JohnZabroski:而不是
text[I]
?如果必须处理代理项对,则可能会出现这种情况。如果这不是您的意思,我认为您应该在回答中提供完整的代码示例。您已说明应使用该方法,但没有说明应如何使用该方法来解决实际问题。