• java.lang.String中的trim()方法的详细说明(转)


    String.Trim()方法到底为我们做了什么,仅仅是去除字符串两端的空格吗?

    一直以为Trim()方法就是把字符串两端的空格字符给删去,其实我错了,而且错的比较离谱。

    首先我直接反编译String类,找到Trim()方法:

    1 public string Trim()
    2 {
    3     return this.TrimHelper(WhitespaceChars, 2);
    4 }

    TrimHelper方法有两个参数,第一个参数名WhitespaceChars,首字母尽然是大写的,肯定有文章,真不出我所料:

    1 internal static readonly char[] WhitespaceChars;

     这里只是定义它,没有赋值,而且是静态的,我们看看构造函数去,果然找到:

    1 static String()
    2 { Empty = " "; WhitespaceChars = new char[] { '/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', '?', ' ', ' ', ' ', ' ', '?', '?', '?', '?', '?', ' ', '?', '?', '/u2028', '/u2029', ' ', '?' }; }  
    Trim方法就是把字符串两端的这些字符给删去?我很坚定的猜想到。

    继续我们的探索,直接反编译TrimHelper,哇,也许这个才是我想要的,私有的TrimHelper方法:

     1 private string TrimHelper(char[] trimChars, int trimType)
     2 {
     3     int num = this.Length - 1;
     4     int startIndex = 0;
     5     if (trimType != 1)
     6     {
     7         startIndex = 0;
     8         while (startIndex < this.Length)
     9         {
    10             int index = 0;
    11             char ch = this[startIndex];
    12             index = 0;
    13             while (index < trimChars.Length)
    14             {
    15                 if (trimChars[index] == ch)
    16                 {
    17                     break;
    18                 }
    19                 index++;
    20             }
    21             if (index == trimChars.Length)
    22             {
    23                 break;
    24             }
    25             startIndex++;
    26         }
    27     }
    28     if (trimType != 0)
    29     {
    30         num = this.Length - 1;
    31         while (num >= startIndex)
    32         {
    33             int num4 = 0;
    34             char ch2 = this[num];
    35             num4 = 0;
    36             while (num4 < trimChars.Length)
    37             {
    38                 if (trimChars[num4] == ch2)
    39                 {
    40                     break;
    41                 }
    42                 num4++;
    43             }
    44             if (num4 == trimChars.Length)
    45             {
    46                 break;
    47             }
    48             num--;
    49         }
    50     }
    51     int length = (num - startIndex) + 1;
    52     if (length == this.Length)
    53     {
    54         return this;
    55     }
    56     if (length == 0)
    57     {
    58         return Empty;
    59     }
    60     return this.InternalSubString(startIndex, length, false);
    61 }

     经过分析和运行,基本上知道了这个方法是干什么的了。

    TrimHelper方法有两个参数:

    第一个参数trimChars,是要从字符串两端删除掉的字符的数组;

    第二个参数trimType,是标识Trim的类型。就目前发现,trimType的取值有3个。当传入0时,去除字符串头部的空白字符,传入1时去除字符串尾部的空白字符,传入其他数值(比如2) 去除字符串两端的空白字符。

    最后再看看真正执行字符串截取的方法:

     1 private unsafe string InternalSubString(int startIndex, int length, bool fAlwaysCopy)
     2 {
     3     if (((startIndex == 0) && (length == this.Length)) && !fAlwaysCopy)
     4     {
     5         return this;
     6     }
     7     string str = FastAllocateString(length);
     8     fixed (char* chRef = &str.m_firstChar)
     9     {
    10         fixed (char* chRef2 = &this.m_firstChar)
    11         {
    12             wstrcpy(chRef, chRef2 + startIndex, length);
    13         }
    14     }
    15     return str;
    16 }

     原来也用指针的?第一次看到,效率应该比较高吧。 
    最后总结一下: 
    String.Trim()方法会去除字符串两端,不仅仅是空格字符,它总共能去除25种字符: 
    ('/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '?', '/u2028', '/u2029', ' ', '?')


    如果你想保留其中的一个或多个(例如/t制表符,/n换行符,/r回车符等),请慎用Trim方法。

    请注意,Trim删除的过程为从外到内,直到碰到一个非空白的字符为止,所以不管前后有多少个连续的空白字符都会被删除掉。

     最后附上两个相关的方法(也是String类直接提供的),分别去除字符串头部空白字符的TrimStart方法和去除字符串尾部空白字符的 TrimEnd方法:

    TrimStart和TrimEnd方法

    如果想去除字符串两端其他任意字符,可以考虑Trim他的重载兄弟:String.Trim(Char[]),传入你想要去除的哪些字符的数组。

    源码奉上:

    1 public string Trim(params char[] trimChars)
    2 {
    3     if ((trimChars == null) || (trimChars.Length == 0))
    4     {
    5         trimChars = WhitespaceChars;
    6     }
    7     return this.TrimHelper(trimChars, 2);
    8 }

    空格 != 空白字符,删除空格请使用: Trim(‘ ‘);

  • 相关阅读:
    记录一次有意思的XSS过滤绕过2
    2018年总结
    记录一次Oracle注入绕waf
    记录一次有意思的XSS过滤绕过
    绕过阿里云waf进行SQL注入
    CRLF在过滤XSS语句后打Cookie方式
    JavaWeb之商品查看后历史记录代码实现
    Mysql注入小tips --持续更新中
    JDK动态代理(Proxy)的两种实现方式
    ajax 异步刷新
  • 原文地址:https://www.cnblogs.com/zl1991/p/6278539.html
Copyright © 2020-2023  润新知