在C#语言中,按字符数截取字符串可采用String类的SubString方法实现,但不少状况下,咱们须要按字节数截取字符串。函数
举例来讲,现有一行文字,屏幕上须要展现的界面宽度有限,但文字的总长度可能比界面的宽度要长,这就致使了屏幕上显示不下全部的字,为解决这一问题,有一个办法是只显示字符串开始的部分,而后将后面显示不下的部分替换为省略号(...)。字体
可是,由于全角字符和半角字符的长度是不同的,咱们不能按字符数截取字符串。以下图所示,字符串“1234567890”和“一二三四五六七八九〇”,长度都是10,但后者占据的实际长度是前者的两倍!(若是采用的不是等宽字体,那长度的误差会千奇百怪,本文中的DEMO采用的都是Windows控制台默认的点阵字体)优化
一个半角字符占一个字节,一个全角字符占两个字节,而全角字符在显示上又是半角字符的两倍。 若是咱们能够按字节数截取字符串,就能够保证截取字符串的长度了。code
我先实现了下面这个函数,对字符串进行裁剪。字符串
/// <summary> /// 裁减字符串 - 直接裁减 /// </summary> /// <param name="originalText">被裁减字符串</param> /// <param name="bytesAfterCut">需保留的字节数</param> /// <returns></returns> public static string GetTreatedText(string originalText, int bytesAfterCut) { string treatedText = originalText; byte[] val = Encoding.Default.GetBytes(originalText); if (val.Length > bytesAfterCut) { treatedText = Encoding.Default.GetString(val, 0, bytesAfterCut) + "..."; } return treatedText; }
但这个方法有一个致命的漏洞,即全角字符占据两个字节,若是被裁剪字符串时,下剪的位置刚好将一个全角字符减成两半,那显示出来的字符串的最后面会出现一个问号(?)。string
以下面的程序,对字符串“你好吗”进行裁剪,要求保留5个字节。但“吗”字被保留了半个字节后,就没法正确显示了。class
所以,咱们须要对裁剪方法作一下优化,代码以下:coding
/// <summary> /// 裁减字符串 - 优化版 liwh - 20160523 /// </summary> /// <param name="originalText">被裁减字符串</param> /// <param name="bytesAfterCut">需保留的字节数</param> /// <returns></returns> public static string GetOptimizedText(string originalText, int bytesAfterCut) { string optimizedText = originalText; byte[] val = Encoding.Default.GetBytes(originalText); if (val.Length > bytesAfterCut) { int left = bytesAfterCut / 2; int right = bytesAfterCut; left = left > originalText.Length ? originalText.Length : left; right = right > originalText.Length ? originalText.Length : right; while (left < right - 1) { int mid = (left + right) / 2; if (Encoding.Default.GetBytes(originalText.Substring(0, mid)).Length > bytesAfterCut) { right = mid; } else { left = mid; } } byte[] rightVal = Encoding.Default.GetBytes(originalText.Substring(0, right)); if (rightVal.Length == bytesAfterCut) { optimizedText = originalText.Substring(0, right) + "..."; } else { optimizedText = originalText.Substring(0, left) + "..."; } } return optimizedText; }
若是发现修剪后会致使最后一个全角字符不能正确显示,则应将那个全角字符整个抛弃。以下图所示,“你好吗”经裁剪后,会变为“你好”,只保留了4个字节的内容。程序
最后补充说明下:本文中描述的场景中,都是从第0字节的状况,截取指定字节数的内容。其余应用场景需作适当修改,但思路大致一致。方法
END