我想截断一个字符串,使其长度不超过给定值。我正在向数据库表写入数据,并希望确保写入的值满足列数据类型的约束。

例如,如果我能写以下内容,那就太好了:

string NormalizeLength(string value, int maxLength)
{
    return value.Substring(0, maxLength);
}

不幸的是,这会引发异常,因为maxLength通常超过字符串值的边界。当然,我可以写一个像下面这样的函数,但我希望这样的东西已经存在了。

string NormalizeLength(string value, int maxLength)
{
    return value.Length <= maxLength ? value : value.Substring(0, maxLength);
} 

执行此任务的难以捉摸的API在哪里?有吗?


当前回答

我知道这是一个老问题,但这里有一个很好的解决方案:

public static string Truncate(this string text, int maxLength, string suffix = "...")
{
    string str = text;
    if (maxLength > 0)
    {
        int length = maxLength - suffix.Length;
        if (length <= 0)
        {
            return str;
        }
        if ((text != null) && (text.Length > maxLength))
        {
            return (text.Substring(0, length).TrimEnd(new char[0]) + suffix);
        }
    }
    return str;
}

var myString = "hello world"
var myTruncatedString = myString.Truncate(4);

返回:你好……

其他回答

我知道这是一个老问题,但这里有一个很好的解决方案:

public static string Truncate(this string text, int maxLength, string suffix = "...")
{
    string str = text;
    if (maxLength > 0)
    {
        int length = maxLength - suffix.Length;
        if (length <= 0)
        {
            return str;
        }
        if ((text != null) && (text.Length > maxLength))
        {
            return (text.Substring(0, length).TrimEnd(new char[0]) + suffix);
        }
    }
    return str;
}

var myString = "hello world"
var myTruncatedString = myString.Truncate(4);

返回:你好……

我更喜欢jpierson的答案,但我在这里看到的示例都没有处理无效的maxLength参数,例如当maxLength < 0时。

可以选择在try/catch中处理错误,将maxLength参数min限制为0,或者如果maxLength小于0则返回空字符串。

未优化的代码:

public string Truncate(this string value, int maximumLength)
{
    if (string.IsNullOrEmpty(value) == true) { return value; }
    if (maximumLen < 0) { return String.Empty; }
    if (value.Length > maximumLength) { return value.Substring(0, maximumLength); }
    return value;
}

这是我通常使用的代码:

string getSubString(string value, int index, int length)
        {
            if (string.IsNullOrEmpty(value) || value.Length <= length)
            {
                return value;
            }
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = index; i < length; i++)
            {
                sb.AppendLine(value[i].ToString());
            }
            return sb.ToString();
        }

因为性能测试很有趣:(使用linqpad扩展方法)

var val = string.Concat(Enumerable.Range(0, 50).Select(i => i % 10));

foreach(var limit in new[] { 10, 25, 44, 64 })
    new Perf<string> {
        { "newstring" + limit, n => new string(val.Take(limit).ToArray()) },
        { "concat" + limit, n => string.Concat(val.Take(limit)) },
        { "truncate" + limit, n => val.Substring(0, Math.Min(val.Length, limit)) },
        { "smart-trunc" + limit, n => val.Length <= limit ? val : val.Substring(0, limit) },
        { "stringbuilder" + limit, n => new StringBuilder(val, 0, Math.Min(val.Length, limit), limit).ToString() },
    }.Vs();

截断法“明显”更快。# microoptimization

早期

truncate10 5788滴答流逝(0.5788 ms) [10K次,5.788E-05 ms /次] smart-trunc10 8206滴答流逝(0.8206 ms) [10K次,8.206E-05 ms /次] stringbuilder10 10557滴答流逝(1.0557 ms) [10K次,0.00010557 ms /次] concat10 45495滴答流逝(4.5495 ms) [10K次,0.00045495 ms /次] 时间流逝(7.2535 ms) [10K次,0.00072535 ms /次]

Late

truncate44 8835滴答流逝(0.8835 ms) [10K次,8.835E-05 ms /次] 13106滴答流逝(1.3106 ms) [10K次,0.00013106 ms /次] smart-trunc44 14821滴答流逝(1.4821毫秒)[10K次,0.00014821毫秒/次] 时间流逝(14.4324 ms) [10K次,0.00144324 ms /次] concat44 174610滴答流逝(17.461毫秒)[每10K次,0.0017461毫秒]

太长时间

smart-trunc64 6944滴答流逝(0.6944毫秒)[在10K次中,6.944E-05毫秒每] truncate64 7686滴答流逝(0.7686 ms) [10K次,7.686E-05 ms /次] stringbuilder64 13314滴答流逝(1.3314 ms) [10K次,0.00013314 ms /次] 时间流逝(17.7481 ms) [10K次,0.00177481 ms /次] concat64 241601滴答流逝(24.1601毫秒)[每10K次,0.00241601毫秒]

我知道已经有大量的答案,但我的需要是保持字符串的开始和结束完整,但缩短到最大长度以下。

    public static string TruncateMiddle(string source)
    {
        if (String.IsNullOrWhiteSpace(source) || source.Length < 260) 
            return source;

        return string.Format("{0}...{1}", 
            source.Substring(0, 235),
            source.Substring(source.Length - 20));
    }

用于创建最大长度为260个字符的SharePoint url。

我没有把长度作为参数,因为它是一个常数260。我也没有将第一个子字符串长度作为参数,因为我希望它在特定的点中断。最后,第二个子字符串是源文件的长度——20,因为我知道文件夹的结构。

这可以很容易地适应您的特定需求。