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

相關文章
相關標籤/搜索