C#实现中英混合字符串精准截取

苏见山
苏见山
发布时间:2026-10-14| 6人浏览过
原创

在Web应用或桌面软件开发中,界面空间有限,常需对包含中英文的长文本进行截断。由于英文通常占1个字节而中文占2个(GB2312/GBK)或3-4个字节(UTF-8),直接按字符数截取易导致显示不全或排版错乱。本文将介绍两种基于字节宽度控制的C#字符串截取策略。

核心需求与结果

目标是在指定最大字节长度内截取字符串,并在末尾追加省略号等标识符。关键在于准确判断“剩余可用字节数”,避免因截断位置不当而破坏多字节字符结构。

准备条件

  • C# 环境支持 System.Text.RegularExpressions 和 System.Text 命名空间。
  • 明确目标编码格式(如 GBK 或 ASCII 近似值)。以下示例主要模拟常见的 GBK/双字节汉字特性。

真实操作顺序

第1步:使用正则表达式进行近似宽度计算

目的:快速估算字符串视觉长度,适用于对精度要求不高且追求性能的场景。

入口:定义静态方法 CutStr。

动作:

  1. 接收最大长度 maxLength 和原字符串 str。
  2. 使用正则 [\u4e00-\u9fa5] 匹配所有中文字符,并将其替换为两个英文字符(如 "zz")。这样替换后,字符串的长度即近似等于其在双字节编码下的字节数。
  3. 若替换后的长度小于等于 maxLength,则直接返回原串。
  4. 否则,从后向前遍历截取子串,再次检查替换后的长度是否满足 maxLength - 3(预留 "..." 的空间)。
/// <summary>
/// 截断字符串,基于正则近似计算宽度
/// </summary>
/// <param name="maxLength">最大字节长度</param>
/// <param name="str">原字符串</param>
/// <returns>截断后的字符串</returns>
public static string CutStr(int maxLength, string str)
{
    string temp = str;
    // 将中文替换为2个字符,模拟双字节宽度
    if (Regex.Replace(temp, "[\u4e00-\u9fa5]", "zz", RegexOptions.IgnoreCase).Length <= maxLength)
    {
        return temp;
    }
    
    // 从后向前寻找合适的截断点
    for (int i = temp.Length; i >= 0; i--)
    {
        temp = temp.Substring(0, i);
        // 检查剩余部分加上省略号后是否符合最大长度
        if (Regex.Replace(temp, "[\u4e00-\u9fa5]", "zz", RegexOptions.IgnoreCase).Length <= maxLength - 3)
        {
            return temp + "...";
        }
    }
    return "...";
}

第2步:通过字节数组精确统计宽度

目的:更精细地控制边界,防止在多字节字符中间截断导致乱码。

入口:定义实例方法 GetByteString。

动作:

  1. 首先截取不超过 maxlen + 1 长度的临时字符串,防止越界。
  2. 将其转换为 ASCIIEncoding.ASCII 字节数组。注意:ASCIIEncoding 对于非ASCII字符(如中文)默认返回 '?' (63),这常用于简单估算中文占2字节的场景(尽管实际UTF-8更长,但在GBK环境下此逻辑常见)。
  3. 遍历字节,若值为 63 ('?') 则认为该字符在原串中占2位宽度,否则占1位。
  4. 累加宽度计数 count,仅当总宽度未超过限制时才加入输出字符串。
  5. 最后追加结束符(如省略号)并返回。
private string GetByteString(string center, int maxlen, string endStr)
{
    // 初步截取,防止后续Substring越界
    string temp = center.Substring(0, (center.Length < maxlen + 1) ? center.Length : maxlen + 1);
    
    // 使用ASCII编码获取字节,中文在非ASCII时通常会变成特定字节或问号,此处简化逻辑
    byte[] encodedBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(temp);
    string outputStr = "";
    int count = 0;
    
    for (int i = 0; i < temp.Length; i++)
    {
        // 如果字节值为63('?'),在某些编码假设下代表占位或中文占用额外字节
        // 注意:此方法依赖特定编码行为,生产环境建议根据实际Encoding调整
        if ((int)encodedBytes[i] == 63)
            count += 2;
        else
            count += 1;

        if (count <= maxlen - endStr.Length)
          outputStr += temp.Substring(i, 1);
        else if (count > maxlen)
          break;
    }
    
    // 如果全程未超限,恢复完整字符串并移除尾缀
    if (count <= maxlen)
    {
        outputStr = temp;
        endStr = "";
    }
    outputStr += endStr;
    return outputStr;
}

完成判断

调用上述函数后,返回的字符串长度(以字节计)应严格控制在传入的 maxLength 以内,且末尾附带指定的结束符号。可在单元测试中传入包含大量中文和英文的混合字符串验证其表现。

简要总结

中英混合字符串截取的核心在于区分“字符数”与“显示宽度”。方法一利用正则替换快速估算,适合通用场景;方法二通过字节分析提供更底层的控制。开发者可根据项目实际的编码标准(GBK/UTF-8)选择合适的实现方式。以上就是C#中英文混合字符串截取函数的详细内容,更多关于C#字符串处理技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。