首页

关于apache-shiro源码包中StringUtils字符串工具类进行常用的字符串处理

标签:apache,shiro,StringUtils,字符串工具类     发布时间:2018-05-24   

一、前言

关于apaceshiro源码包org.apache.shiro.util.StringUtils字符串工具类,进行字符串判断是否有文本hasText、对象数组转字符串toString、集合转字符串数组toStringArray、分隔内容行为字符串数组splitKeyValue等。

二、源码说明 

package org.apache.shiro.util;@b@@b@import java.text.ParseException;@b@import java.util.*;@b@ @b@public class StringUtils {@b@@b@     @b@    public static final String EMPTY_STRING = "";@b@@b@    /**@b@     * Constant representing the default delimiter character (comma), equal to <code>','</code>@b@     */@b@    public static final char DEFAULT_DELIMITER_CHAR = ',';@b@@b@    /**@b@     * Constant representing the default quote character (double quote), equal to '&quot;'</code>@b@     */@b@    public static final char DEFAULT_QUOTE_CHAR = '"';@b@@b@    /**@b@     * Check whether the given String has actual text.@b@     * More specifically, returns <code>true</code> if the string not <code>null</code>,@b@     * its length is greater than 0, and it contains at least one non-whitespace character.@b@     * <p/>@b@     * <code>StringUtils.hasText(null) == false<br/>@b@     * StringUtils.hasText("") == false<br/>@b@     * StringUtils.hasText(" ") == false<br/>@b@     * StringUtils.hasText("12345") == true<br/>@b@     * StringUtils.hasText(" 12345 ") == true</code>@b@     * <p/>@b@     * <p>Copied from the Spring Framework while retaining all license, copyright and author information.@b@     *@b@     * @param str the String to check (may be <code>null</code>)@b@     * @return <code>true</code> if the String is not <code>null</code>, its length is@b@     *         greater than 0, and it does not contain whitespace only@b@     * @see java.lang.Character#isWhitespace@b@     */@b@    public static boolean hasText(String str) {@b@        if (!hasLength(str)) {@b@            return false;@b@        }@b@        int strLen = str.length();@b@        for (int i = 0; i < strLen; i++) {@b@            if (!Character.isWhitespace(str.charAt(i))) {@b@                return true;@b@            }@b@        }@b@        return false;@b@    }@b@@b@    /**@b@     * Check that the given String is neither <code>null</code> nor of length 0.@b@     * Note: Will return <code>true</code> for a String that purely consists of whitespace.@b@     * <p/>@b@     * <code>StringUtils.hasLength(null) == false<br/>@b@     * StringUtils.hasLength("") == false<br/>@b@     * StringUtils.hasLength(" ") == true<br/>@b@     * StringUtils.hasLength("Hello") == true</code>@b@     * <p/>@b@     * Copied from the Spring Framework while retaining all license, copyright and author information.@b@     *@b@     * @param str the String to check (may be <code>null</code>)@b@     * @return <code>true</code> if the String is not null and has length@b@     * @see #hasText(String)@b@     */@b@    public static boolean hasLength(String str) {@b@        return (str != null && str.length() > 0);@b@    }@b@@b@@b@    /**@b@     * Test if the given String starts with the specified prefix,@b@     * ignoring upper/lower case.@b@     * <p/>@b@     * <p>Copied from the Spring Framework while retaining all license, copyright and author information.@b@     *@b@     * @param str    the String to check@b@     * @param prefix the prefix to look for@b@     * @return <code>true</code> starts with the specified prefix (ignoring case), <code>false</code> if it does not.@b@     * @see java.lang.String#startsWith@b@     */@b@    public static boolean startsWithIgnoreCase(String str, String prefix) {@b@        if (str == null || prefix == null) {@b@            return false;@b@        }@b@        if (str.startsWith(prefix)) {@b@            return true;@b@        }@b@        if (str.length() < prefix.length()) {@b@            return false;@b@        }@b@        String lcStr = str.substring(0, prefix.length()).toLowerCase();@b@        String lcPrefix = prefix.toLowerCase();@b@        return lcStr.equals(lcPrefix);@b@    }@b@@b@    /**@b@     * Returns a 'cleaned' representation of the specified argument.  'Cleaned' is defined as the following:@b@     * <p/>@b@     * <ol>@b@     * <li>If the specified <code>String</code> is <code>null</code>, return <code>null</code></li>@b@     * <li>If not <code>null</code>, {@link String#trim() trim()} it.</li>@b@     * <li>If the trimmed string is equal to the empty String (i.e. &quot;&quot;), return <code>null</code></li>@b@     * <li>If the trimmed string is not the empty string, return the trimmed version</li>.@b@     * </ol>@b@     * <p/>@b@     * Therefore this method always ensures that any given string has trimmed text, and if it doesn't, <code>null</code>@b@     * is returned.@b@     *@b@     * @param in the input String to clean.@b@     * @return a populated-but-trimmed String or <code>null</code> otherwise@b@     */@b@    public static String clean(String in) {@b@        String out = in;@b@@b@        if (in != null) {@b@            out = in.trim();@b@            if (out.equals(EMPTY_STRING)) {@b@                out = null;@b@            }@b@        }@b@@b@        return out;@b@    }@b@@b@    /**@b@     * Returns the specified array as a comma-delimited (',') string.@b@     *@b@     * @param array the array whose contents will be converted to a string.@b@     * @return the array's contents as a comma-delimited (',') string.@b@     * @since 1.0@b@     */@b@    public static String toString(Object[] array) {@b@        return toDelimitedString(array, ",");@b@    }@b@@b@    /**@b@     * Returns the array's contents as a string, with each element delimited by the specified@b@     * {@code delimiter} argument.  Useful for {@code toString()} implementations and log messages.@b@     *@b@     * @param array     the array whose contents will be converted to a string@b@     * @param delimiter the delimiter to use between each element@b@     * @return a single string, delimited by the specified {@code delimiter}.@b@     * @since 1.0@b@     */@b@    public static String toDelimitedString(Object[] array, String delimiter) {@b@        if (array == null || array.length == 0) {@b@            return EMPTY_STRING;@b@        }@b@        StringBuilder sb = new StringBuilder();@b@        for (int i = 0; i < array.length; i++) {@b@            if (i > 0) {@b@                sb.append(delimiter);@b@            }@b@            sb.append(array[i]);@b@        }@b@        return sb.toString();@b@    }@b@@b@    /**@b@     * Returns the collection's contents as a string, with each element delimited by the specified@b@     * {@code delimiter} argument.  Useful for {@code toString()} implementations and log messages.@b@     *@b@     * @param c         the collection whose contents will be converted to a string@b@     * @param delimiter the delimiter to use between each element@b@     * @return a single string, delimited by the specified {@code delimiter}.@b@     * @since 1.2@b@     */@b@    public static String toDelimitedString(Collection c, String delimiter) {@b@        if (c == null || c.isEmpty()) {@b@            return EMPTY_STRING;@b@        }@b@        return join(c.iterator(), delimiter);@b@    }@b@@b@    /**@b@     * Tokenize the given String into a String array via a StringTokenizer.@b@     * Trims tokens and omits empty tokens.@b@     * <p>The given delimiters string is supposed to consist of any number of@b@     * delimiter characters. Each of those characters can be used to separate@b@     * tokens. A delimiter is always a single character; for multi-character@b@     * delimiters, consider using <code>delimitedListToStringArray</code>@b@     * <p/>@b@     * <p>Copied from the Spring Framework while retaining all license, copyright and author information.@b@     *@b@     * @param str        the String to tokenize@b@     * @param delimiters the delimiter characters, assembled as String@b@     *                   (each of those characters is inpidually considered as delimiter).@b@     * @return an array of the tokens@b@     * @see java.util.StringTokenizer@b@     * @see java.lang.String#trim()@b@     */@b@    public static String[] tokenizeToStringArray(String str, String delimiters) {@b@        return tokenizeToStringArray(str, delimiters, true, true);@b@    }@b@@b@    /**@b@     * Tokenize the given String into a String array via a StringTokenizer.@b@     * <p>The given delimiters string is supposed to consist of any number of@b@     * delimiter characters. Each of those characters can be used to separate@b@     * tokens. A delimiter is always a single character; for multi-character@b@     * delimiters, consider using <code>delimitedListToStringArray</code>@b@     * <p/>@b@     * <p>Copied from the Spring Framework while retaining all license, copyright and author information.@b@     *@b@     * @param str               the String to tokenize@b@     * @param delimiters        the delimiter characters, assembled as String@b@     *                          (each of those characters is inpidually considered as delimiter)@b@     * @param trimTokens        trim the tokens via String's <code>trim</code>@b@     * @param ignoreEmptyTokens omit empty tokens from the result array@b@     *                          (only applies to tokens that are empty after trimming; StringTokenizer@b@     *                          will not consider subsequent delimiters as token in the first place).@b@     * @return an array of the tokens (<code>null</code> if the input String@b@     *         was <code>null</code>)@b@     * @see java.util.StringTokenizer@b@     * @see java.lang.String#trim()@b@     */@b@    @SuppressWarnings({"unchecked"})@b@    public static String[] tokenizeToStringArray(@b@            String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {@b@@b@        if (str == null) {@b@            return null;@b@        }@b@        StringTokenizer st = new StringTokenizer(str, delimiters);@b@        List tokens = new ArrayList();@b@        while (st.hasMoreTokens()) {@b@            String token = st.nextToken();@b@            if (trimTokens) {@b@                token = token.trim();@b@            }@b@            if (!ignoreEmptyTokens || token.length() > 0) {@b@                tokens.add(token);@b@            }@b@        }@b@        return toStringArray(tokens);@b@    }@b@@b@    /**@b@     * Copy the given Collection into a String array.@b@     * The Collection must contain String elements only.@b@     * <p/>@b@     * <p>Copied from the Spring Framework while retaining all license, copyright and author information.@b@     *@b@     * @param collection the Collection to copy@b@     * @return the String array (<code>null</code> if the passed-in@b@     *         Collection was <code>null</code>)@b@     */@b@    @SuppressWarnings({"unchecked"})@b@    public static String[] toStringArray(Collection collection) {@b@        if (collection == null) {@b@            return null;@b@        }@b@        return (String[]) collection.toArray(new String[collection.size()]);@b@    }@b@@b@    public static String[] splitKeyValue(String aLine) throws ParseException {@b@        String line = clean(aLine);@b@        if (line == null) {@b@            return null;@b@        }@b@        String[] split = line.split(" ", 2);@b@        if (split.length != 2) {@b@            //fallback to checking for an equals sign@b@            split = line.split("=", 2);@b@            if (split.length != 2) {@b@                String msg = "Unable to determine Key/Value pair from line [" + line + "].  There is no space from " +@b@                        "which the split location could be determined.";@b@                throw new ParseException(msg, 0);@b@            }@b@@b@        }@b@@b@        split[0] = clean(split[0]);@b@        split[1] = clean(split[1]);@b@        if (split[1].startsWith("=")) {@b@            //they used spaces followed by an equals followed by zero or more spaces to split the key/value pair, so@b@            //remove the equals sign to result in only the key and values in the@b@            split[1] = clean(split[1].substring(1));@b@        }@b@@b@        if (split[0] == null) {@b@            String msg = "No valid key could be found in line [" + line + "] to form a key/value pair.";@b@            throw new ParseException(msg, 0);@b@        }@b@        if (split[1] == null) {@b@            String msg = "No corresponding value could be found in line [" + line + "] for key [" + split[0] + "]";@b@            throw new ParseException(msg, 0);@b@        }@b@@b@        return split;@b@    }@b@@b@    public static String[] split(String line) {@b@        return split(line, DEFAULT_DELIMITER_CHAR);@b@    }@b@@b@    public static String[] split(String line, char delimiter) {@b@        return split(line, delimiter, DEFAULT_QUOTE_CHAR);@b@    }@b@@b@    public static String[] split(String line, char delimiter, char quoteChar) {@b@        return split(line, delimiter, quoteChar, quoteChar);@b@    }@b@@b@    public static String[] split(String line, char delimiter, char beginQuoteChar, char endQuoteChar) {@b@        return split(line, delimiter, beginQuoteChar, endQuoteChar, false, true);@b@    }@b@@b@    /**@b@     * Splits the specified delimited String into tokens, supporting quoted tokens so that quoted strings themselves@b@     * won't be tokenized.@b@     * <p/>@b@     * This method's implementation is very loosely based (with significant modifications) on@b@     * <a href="http://blogs.bytecode.com.au/glen">Glen Smith</a>'s open-source@b@     * <a href="http://opencsv.svn.sourceforge.net/viewvc/opencsv/trunk/src/au/com/bytecode/opencsv/CSVReader.java?&view=markup">CSVReader.java</a>@b@     * file.@b@     * <p/>@b@     * That file is Apache 2.0 licensed as well, making Glen's code a great starting point for us to modify to@b@     * our needs.@b@     *@b@     * @param aLine          the String to parse@b@     * @param delimiter      the delimiter by which the <tt>line</tt> argument is to be split@b@     * @param beginQuoteChar the character signifying the start of quoted text (so the quoted text will not be split)@b@     * @param endQuoteChar   the character signifying the end of quoted text@b@     * @param retainQuotes   if the quotes themselves should be retained when constructing the corresponding token@b@     * @param trimTokens     if leading and trailing whitespace should be trimmed from discovered tokens.@b@     * @return the tokens discovered from parsing the given delimited <tt>line</tt>.@b@     */@b@    public static String[] split(String aLine, char delimiter, char beginQuoteChar, char endQuoteChar,@b@                                 boolean retainQuotes, boolean trimTokens) {@b@        String line = clean(aLine);@b@        if (line == null) {@b@            return null;@b@        }@b@@b@        List<String> tokens = new ArrayList<String>();@b@        StringBuilder sb = new StringBuilder();@b@        boolean inQuotes = false;@b@@b@        for (int i = 0; i < line.length(); i++) {@b@@b@            char c = line.charAt(i);@b@            if (c == beginQuoteChar) {@b@                // this gets complex... the quote may end a quoted block, or escape another quote.@b@                // do a 1-char lookahead:@b@                if (inQuotes  // we are in quotes, therefore there can be escaped quotes in here.@b@                        && line.length() > (i + 1)  // there is indeed another character to check.@b@                        && line.charAt(i + 1) == beginQuoteChar) { // ..and that char. is a quote also.@b@                    // we have two quote chars in a row == one quote char, so consume them both and@b@                    // put one on the token. we do *not* exit the quoted text.@b@                    sb.append(line.charAt(i + 1));@b@                    i++;@b@                } else {@b@                    inQuotes = !inQuotes;@b@                    if (retainQuotes) {@b@                        sb.append(c);@b@                    }@b@                }@b@            } else if (c == endQuoteChar) {@b@                inQuotes = !inQuotes;@b@                if (retainQuotes) {@b@                    sb.append(c);@b@                }@b@            } else if (c == delimiter && !inQuotes) {@b@                String s = sb.toString();@b@                if (trimTokens) {@b@                    s = s.trim();@b@                }@b@                tokens.add(s);@b@                sb = new StringBuilder(); // start work on next token@b@            } else {@b@                sb.append(c);@b@            }@b@        }@b@        String s = sb.toString();@b@        if (trimTokens) {@b@            s = s.trim();@b@        }@b@        tokens.add(s);@b@        return tokens.toArray(new String[tokens.size()]);@b@    }@b@@b@    /**@b@     * Joins the elements of the provided {@code Iterator} into@b@     * a single String containing the provided elements.</p>@b@     * <p/>@b@     * No delimiter is added before or after the list.@b@     * A {@code null} separator is the same as an empty String ("").</p>@b@     * <p/>@b@     * Copied from Commons Lang, version 3 (r1138702).</p>@b@     *@b@     * @param iterator  the {@code Iterator} of values to join together, may be null@b@     * @param separator the separator character to use, null treated as ""@b@     * @return the joined String, {@code null} if null iterator input@b@     * @since 1.2@b@     */@b@    public static String join(Iterator<?> iterator, String separator) {@b@        final String empty = "";@b@@b@        // handle null, zero and one elements before building a buffer@b@        if (iterator == null) {@b@            return null;@b@        }@b@        if (!iterator.hasNext()) {@b@            return empty;@b@        }@b@        Object first = iterator.next();@b@        if (!iterator.hasNext()) {@b@            return first == null ? empty : first.toString();@b@        }@b@@b@        // two or more elements@b@        StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small@b@        if (first != null) {@b@            buf.append(first);@b@        }@b@@b@        while (iterator.hasNext()) {@b@            if (separator != null) {@b@                buf.append(separator);@b@            }@b@            Object obj = iterator.next();@b@            if (obj != null) {@b@                buf.append(obj);@b@            }@b@        }@b@        return buf.toString();@b@    }@b@@b@    /**@b@     * Splits the {@code delimited} string (delimited by the specified {@code separator} character) and returns the@b@     * delimited values as a {@code Set}.@b@     * <p/>@b@     * If either argument is {@code null}, this method returns {@code null}.@b@     *@b@     * @param delimited the string to split@b@     * @param separator the character that delineates inpidual tokens to split@b@     * @return the delimited values as a {@code Set}.@b@     * @since 1.2@b@     */@b@    public static Set<String> splitToSet(String delimited, String separator) {@b@        if (delimited == null || separator == null) {@b@            return null;@b@        }@b@        String[] split = split(delimited, separator.charAt(0));@b@        return asSet(split);@b@    }@b@@b@    /**@b@     * Returns the input argument, but ensures the first character is capitalized (if possible).@b@     * @param in the string to uppercase the first character.@b@     * @return the input argument, but with the first character capitalized (if possible).@b@     * @since 1.2@b@     */@b@    public static String uppercaseFirstChar(String in) {@b@        if (in == null || in.length() == 0) {@b@            return in;@b@        }@b@        int length = in.length();@b@        StringBuilder sb = new StringBuilder(length);@b@@b@        sb.append(Character.toUpperCase(in.charAt(0)));@b@        if (length > 1) {@b@            String remaining = in.substring(1);@b@            sb.append(remaining);@b@        }@b@        return sb.toString();@b@    }@b@@b@    //////////////////////////@b@    // From CollectionUtils //@b@    //////////////////////////@b@    // CollectionUtils cannot be removed from shiro-core until 2.0 as it has a dependency on PrincipalCollection@b@@b@@b@    private static <E> Set<E> asSet(E... elements) {@b@        if (elements == null || elements.length == 0) {@b@            return Collections.emptySet();@b@        }@b@@b@        if (elements.length == 1) {@b@            return Collections.singleton(elements[0]);@b@        }@b@@b@        LinkedHashSet<E> set = new LinkedHashSet<E>(elements.length * 4 / 3 + 1);@b@        Collections.addAll(set, elements);@b@        return set;@b@    }@b@@b@}