C# 中按字节数截取字符串

在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

相关文章
相关标签/搜索