文章列表顯示標題,限制顯示寬度 (以位元組計),中文佔 2 位元組、英文 1 位元組,超出部分補 ...,且不能將中文字元從中間截斷。
public static string GetSubString(string s, int byteLen)
{
if (string.IsNullOrEmpty(s)) return s;
// 將中文字元替換為 "zz" (2 字元),再算 Length 即為位元組長度
string replaced = Regex.Replace(s, "[\u4e00-\u9fa5]", "zz");
if (replaced.Length <= byteLen) return s; // 未超長
// 從尾部往前嘗試截取
for (int i = s.Length; i >= 0; i--)
{
string sub = s.Substring(0, i);
string subReplaced = Regex.Replace(sub, "[\u4e00-\u9fa5]", "zz");
if (subReplaced.Length <= byteLen - 3) // 預留 "..." 3 位元組
{
return sub + "...";
}
}
return "...";
}
string s1 = "中國人要啊abc呀~";
string s2 = "1中國人23456abc呀~";
Console.WriteLine(GetSubString(s1, 8)); // 中國人要...
Console.WriteLine(GetSubString(s2, 8)); // 1中國人2...
\u4e00-\u9fa5 涵蓋常用漢字。"zz",Length 即等同位元組長度 (假設雙位元組編碼)。... 的 3 位元組後再比較。public static string GetSubStringFast(string s, int byteLen)
{
if (string.IsNullOrEmpty(s)) return s;
byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(s); // 或 Big5
if (bytes.Length <= byteLen) return s;
int charCount = Encoding.GetEncoding("GB2312").GetChars(bytes, 0, byteLen - 3).Length;
return s.Substring(0, charCount) + "...";
}
直接用編碼器轉換,一次運算得出字元數,效能大幅提升,且自動處理截半字元問題 (解碼器會捨棄不完整位元組序列)。
Regex 替換法邏輯清晰易懂;編碼器法效能更佳且自動處理邊界。依專案效能需求選擇。