在Windows Phone上,我想将任何给定字符串子串到相当于100个ASCII字符的长度。
String.Length显然没用,因为中文字符串每个字符使用3个字节,丹麦字符串每个字符使用2个或4个字节,俄语字符串每个字符使用4个字节。
唯一可用的编码是UTF-8和UTF-16。那我该怎么办?
这个想法是这样的:
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));
}
但是长度需要使用每个字符使用的字节数正确分割,因此 last 字符始终可以正确呈现。
答案 0 :(得分:6)
一个选项是简单地浏览字符串,计算每个字符的字节数。
如果您知道不需要处理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;
}
如果你必须处理代理人对,那就变得有点棘手了:(
答案 1 :(得分:1)
一种选择是简单地将“字符”(包括代理对,如果你需要支持它们)添加到结果字符串中,看看它是否被转换成你想要的正确数字。
答案 2 :(得分:1)
尽管这是一个非常老的问题,但我认为正确的方法是使用System.Globalization.StringInfo
类的StringInfo.SubstringByTextElements
Method。这样做的主要优点是对net461
及更高版本的.NET文档保证,StringInfo
的{{3}}保证符合Unicode标准版本8.0.0:
给来电者的记录
内部,StringInfo类的方法调用 CharUnicodeInfo类确定字符的方法 类别。从.NET Framework 4.6.2开始,字符 分类基于Unicode标准版本8.0.0。对于 NET Framework 4.6.1至.NET Framework 4,它基于 Unicode标准版本6.3.0。在.NET Core中,它基于 Unicode标准版本8.0.0。
现在,鉴于Microsoft Docs上没有有关如何调用它的示例,您如何实际调用SubstringByTextElements?
在StringInfo
类中,有一个注释说:
- 通过调用
ParseCombiningCharacters
方法来检索包含每个文本元素的起始索引的数组。然后,您可以通过将这些索引传递给SubstringByTextElements
方法来检索单个文本元素。
所以:
答案 3 :(得分:0)
还有一个想法是检查最后一个字符是否为Unicode Replace Character,并删除一个字符,直到它被正确呈现。
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;
}