C# 按字节数截取字符串并添加省略号的实现
C# 内置的字符串截取主要基于字符数量而非字节数,但在处理数据库存储、日志打印或 API 传输等受字节长度限制的场景时,需要精确控制。由于不同字符(如中文与英文)在不同编码下占用的字节不同,直接按字符数截取易导致末尾字符被截断一半而引发乱码。本文将演示如何通过遍历字符并累加字节长度,安全地将字符串截断到指定字节并在末端补充 "..."。
按字节数截取并追加省略号的方法
该函数的核心逻辑是依次读取字符串中的每个字符,将其转换为指定的字节编码并累加计数。一旦累计字节数达到或超过目标值,立即停止循环并返回子串。这种方法能有效避免将双字节或三字节字符截断为非法字节序列。
第1步:定义包含省略号的截取函数
首先引入必要的命名空间(若未全局引入),并创建静态辅助方法 GetSubString。以下是完整的 C# 实现代码:
public static string GetSubString(string origStr, int endIndex)
{
// 1. 边界检查:输入为空或截取长度为负数时,直接返回空字符串
if (origStr == null || origStr.Length == 0 || endIndex < 0)
return "";
// 此处使用 gb2312 编码计算总字节数(可根据实际需求切换为 Encoding.UTF8)
int bytesCount = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(origStr);
// 如果总字节数不超过限制,直接返回原字符串
if (bytesCount <= endIndex)
return origStr;
int readyLength = 0;
int byteLength;
// 2. 逐字符累加字节数
for (int i = 0; i < origStr.Length; i++)
{
// 获取单个字符在当前编码下的字节长度
byteLength = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(new char[] { origStr[i] });
readyLength += byteLength;
// 3. 当刚好等于目标长度时,截取包含当前字符的部分并加上省略号
if (readyLength == endIndex)
{
origStr = origStr.Substring(0, i + 1) + "...";
break;
}
// 4. 当超过目标长度时,不截取当前字符,保持之前的截断位置,并加上省略号
else if (readyLength > endIndex)
{
origStr = origStr.Substring(0, i) + "...";
break;
}
}
return origStr;
}
第2步:理解参数与执行结果
- 参数说明:
origStr:需要进行截断处理的原始字符串。endIndex:截取的目标字节总数(例如:10代表最多占用10个字节)。
- 注意事项:
- 原代码中使用了
Encoding.GetEncoding("gb2312")。如果您的系统环境默认为 UTF-8(如在 Linux 服务器或现代 Web 开发中),请替换为Encoding.UTF8,否则可能导致中文显示为乱码或占用字节计算偏差。 - 算法通过逐个字符增加长度,确保了不会切断一个汉字的中间部分。比如遇到一个 2 字节的汉字,若前 1 个字节已达上限,则该字符会被整体舍弃。
- 原代码中使用了
无后缀的精确字节截取方案
在某些 UI 界面设计或数据对齐场景中,可能只需要纯粹的截断而不希望出现末尾的标点符号。逻辑与上述方法一致,唯一的区别是移除字符串拼接操作。
// 按字节数截取字符串(不带省略号)
public static string GetSub1String(string origStr, int endIndex)
{
if (origStr == null || origStr.Length == 0 || endIndex < 0)
return "";
int bytesCount = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(origStr);
if (bytesCount > endIndex)
{
int readyLength = 0;
int byteLength;
for (int i = 0; i < origStr.Length; i++)
{
byteLength = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(new char[] { origStr[i] });
readyLength += byteLength;
// 相等或大于时的截取逻辑略去了省略号拼接
if (readyLength == endIndex)
{
origStr = origStr.Substring(0, i + 1);
break;
}
else if (readyLength > endIndex)
{
origStr = origStr.Substring(0, i);
break;
}
}
}
return origStr;
}
性能优化建议
上述 `for` 循环方式虽然直观且准确,但如果字符串极长或调用频率极高,频繁实例化数组 new char[] { ... } 可能会产生一定开销。在实际生产环境中,如果确认使用的是固定宽度编码或者为了追求极致性能,也可以结合正则表达式或更底层的 `System.Text.Encoding` 缓冲区处理方法进行优化,但对于常规业务逻辑,当前的逐字累加法足以保证安全性与可读性。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









