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

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

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在哪里?有吗?


当前回答

基于这个和这个,这里有两个版本,将适用于“到”值的负值。第一个函数不允许负数无声地设置为0:

public static string Truncate(this string value, int maxLength)
{
    return string.IsNullOrEmpty(value) ?
        value :
        value.Substring(0, Math.Max(0, Math.Min(value.Length, maxLength)));
}

这是一个循环:

private static int Mod(this int a, int n) => (((a %= n) < 0) ? n : 0) + a;

public static string Truncate(this string value, int maxLength)
{
    return string.IsNullOrEmpty(value) ?
        value :
        value.Substring(0, maxLength.Mod(value.Length));
}

其他回答

出于(过度)复杂性的考虑,我将添加重载版本,它将maxLength参数的最后3个字符替换为省略号。

public static string Truncate(this string value, int maxLength, bool replaceTruncatedCharWithEllipsis = false)
{
    if (replaceTruncatedCharWithEllipsis && maxLength <= 3)
        throw new ArgumentOutOfRangeException("maxLength",
            "maxLength should be greater than three when replacing with an ellipsis.");

    if (String.IsNullOrWhiteSpace(value)) 
        return String.Empty;

    if (replaceTruncatedCharWithEllipsis &&
        value.Length > maxLength)
    {
        return value.Substring(0, maxLength - 3) + "...";
    }

    return value.Substring(0, Math.Min(value.Length, maxLength)); 
}

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

    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,因为我知道文件夹的结构。

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

.NET框架有一个API可以像这样截断字符串:

Microsoft.VisualBasic.Strings.Left(string, int);

但在c#应用程序中,你可能更喜欢编写自己的程序,而不是依赖于Microsoft.VisualBasic.dll,后者存在的主要原因是向后兼容。

作为上述可能性的补充,我想分享一下我的解决方案。 它是一个扩展方法,允许null(返回string.Empty),还有第二个. truncate()用于与省略号一起使用。注意,它不是性能优化的。

public static string Truncate(this string value, int maxLength) =>
    (value ?? string.Empty).Substring(0, (value?.Length ?? 0) <= (maxLength < 0 ? 0 : maxLength) ? (value?.Length ?? 0) : (maxLength < 0 ? 0 : maxLength));
public static string Truncate(this string value, int maxLength, string ellipsis) =>
    string.Concat(value.Truncate(maxLength - (((value?.Length ?? 0) > maxLength ? ellipsis : null)?.Length ?? 0)), ((value?.Length ?? 0) > maxLength ? ellipsis : null)).Truncate(maxLength);

流行的Humanizer库有一个Truncate方法。使用NuGet安装:

Install-Package Humanizer