com.feilong.core.lang.StringUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.feilong.core.lang.StringUtil.java

Source

/*
 * Copyright (C) 2008 feilong
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.feilong.core.lang;

import static org.apache.commons.lang3.StringUtils.EMPTY;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.text.StrSubstitutor;

import com.feilong.core.CharsetType;
import com.feilong.core.UncheckedIOException;
import com.feilong.core.bean.ConvertUtil;

import static com.feilong.core.Validator.isNullOrEmpty;

/**
 * {@link String},?,?,format.
 * 
 * <h3>(split)</h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link #split(String, String)}</li>
 * </ul>
 * </blockquote>
 * 
 * <h3>(tokenize)</h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link #tokenizeToStringArray(String, String)}</li>
 * <li>{@link #tokenizeToStringArray(String, String, boolean, boolean)}</li>
 * </ul>
 * 
 * <p>
 * ,split  ? {@link Pattern#split(CharSequence)} (?, $|()[{^?*+\\ ???), {@link StringTokenizer} ,
 * StringTokenizer<br>
 * ,?,{@link StringTokenizer}
 * </p>
 * 
 * </blockquote>
 * 
 * <h3>(search)</h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link StringUtils#countMatches(CharSequence, CharSequence)} </li>
 * </ul>
 * </blockquote>
 * 
 * <h3></h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link StringUtils#capitalize(String)} ?</li>
 * <li>{@link StringUtils#uncapitalize(String)} ????</li>
 * <li>{@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String, char...)} ?,?????</li>
 * </ul>
 * </blockquote>
 * 
 * <h3>{@link String#String(byte[] )}  {@link String#String(byte[], Charset)} </h3>
 * 
 * <blockquote>
 * <p>
 * {@link String#String(byte[] )} {@link String#String(byte[], Charset)};<br>
 *  {@link Charset#defaultCharset()},? ISO-8859-1, ?? {@link java.lang.StringCoding#decode(byte[], int, int) }
 * </p>
 * </blockquote>
 * 
 * <h3>{@link StringBuffer}  {@link StringBuilder}  {@link String} </h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link StringBuffer} ??()</li>
 * <li>{@link StringBuilder} ??(?)</li>
 * <li>{@link String} ?</li>
 * <li> {@link StringBuffer} {@code >} {@link String}</li>
 * <li> {@link StringBuilder} {@code >} {@link StringBuffer}</li>
 * </ul>
 * </blockquote>
 * 
 * <h3>String s1 = new String("xyz");?</h3>
 * 
 * <blockquote>
 * <p>
 * ?.??<br>
 * 1??:HotSpot1.6<br>
 * ?xyz 2,?"xyz"?1<br>
 * 2??:HotSpot1.7<br>
 * ??xyz 1
 * </p>
 * </blockquote>
 * 
 * <h3>String s3 = s1 + s2;<br>
 * System.out.println(s3.intern() == s3);?</h3> <blockquote>
 * <p>
 * ?<br>
 * 1??:hotspot1.6<br>
 * false?<br>
 * 2??:hotspot1.7<br>
 * ?"abcabc",true
 * </p>
 * </blockquote>
 * 
 * <h3>{@link StringUtil#replace(String, String, String)} and {@link #replaceAll(CharSequence, String, String)} and
 * :</h3>
 * 
 * <blockquote>
 * 
 * <table border="1" cellspacing="0" cellpadding="4" summary="">
 * <tr style="background-color:#ccccff">
 * <th align="left"></th>
 * <th align="left"></th>
 * </tr>
 * <tr valign="top">
 * <td>{@link StringUtil#replace(String, String, String)}</td>
 * <td>target??replacement</td>
 * </tr>
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link #replaceAll(CharSequence, String, String)}</td>
 * <td>regex?,???replacement</td>
 * </tr>
 * <tr valign="top">
 * <td>{@link String#replaceFirst(String, String)}</td>
 * <td>{@link StringUtil#replace(String, String, String)},????</td>
 * </tr>
 * </table>
 * 
 * <p>
 * ?:
 * </p>
 * 
 * <pre class="code">
 * StringUtil.replaceAll("SH1265,SH5951", "([a-zA-Z]+[0-9]+)", "'$1'")  ='SH1265','SH5951'
 * StringUtil.replace("SH1265,SH5951", "([a-zA-Z]+[0-9]+)", "'$1'")     =SH1265,SH5951
 * "SH1265,SH5951".replaceFirst("([a-zA-Z]+[0-9]+)", "'$1'")            ='SH1265',SH5951
 * </pre>
 * 
 * </blockquote>
 *
 * @author <a href="http://feitianbenyue.iteye.com/">feilong</a>
 * @see java.util.StringTokenizer
 * @see "org.springframework.util.StringUtils#tokenizeToStringArray(String, String)"
 * @see "org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#MULTI_VALUE_ATTRIBUTE_DELIMITERS"
 * @see org.apache.commons.lang3.StringUtils
 * @see "com.google.common.base.Strings"
 * @since 1.4.0
 */
public final class StringUtil {

    /** Don't let anyone instantiate this class. */
    private StringUtil() {
        //AssertionError?. ?????. ???.
        //see Effective Java 2nd
        throw new AssertionError("No " + getClass().getName() + " instances for you!");
    }

    /**
     * Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
     *
     * @param bytes
     *            The bytes to be decoded into characters, may be <code>null</code>
     * @param charsetType
     *            {@link CharsetType}
     * @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
     *         or <code>null</code> if the input byte array was <code>null</code>.
     * @see String#String(byte[], String)
     * @see "org.apache.commons.lang3.StringUtils#toString(byte[], String)"
     * @see org.apache.commons.lang3.StringUtils#toEncodedString(byte[], Charset)
     * @see "org.apache.commons.codec.binary.StringUtils#newString(byte[], String)"
     * @since 1.3.0
     */
    public static String newString(byte[] bytes, String charsetType) {
        return StringUtils.toEncodedString(bytes, Charset.forName(charsetType));
    }
    // [start]toBytes

    // ********************************************************************************
    /**
     * ??byte.
     *
     * @param value
     *            
     * @return  <code>value</code> null, {@link NullPointerException}<br>
     * @see String#getBytes()
     * @since 1.3.0
     */
    public static byte[] getBytes(String value) {
        Validate.notNull(value, "value can't be null!");
        return value.getBytes();
    }

    /**
     *  <code>value</code> ??byte.
     * 
     * @param value
     *            
     * @param charsetName
     *            ?? charset ??, utf-8, {@link CharsetType}
     * @return  <code>value</code> null, {@link NullPointerException}<br>
     * @see String#getBytes(String)
     * @since 1.3.0
     */
    public static byte[] getBytes(String value, String charsetName) {
        Validate.notNull(value, "value can't be null!");
        try {
            return value.getBytes(charsetName);
        } catch (UnsupportedEncodingException e) {
            throw new UncheckedIOException(e);
        }
    }

    // [end]
    // [start]replace

    // ********************************replace************************************************
    /**
     *  <code>text</code>  <code>searchString</code> ?? <code>replacement</code>.
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <p>
     * A {@code null} reference passed to this method is a no-op.
     * </p>
     *
     * <pre>
     * StringUtil.replace(null, *, *) = null
     * StringUtil.replace("", *, *) = ""
     * StringUtil.replace("any", null, *) = "any"
     * StringUtil.replace("any", *, null) = "any"
     * StringUtil.replace("any", "", *) = "any"
     * StringUtil.replace("aba", "a", null) = "aba"
     * StringUtil.replace("aba", "a", "") = "b"
     * StringUtil.replace("aba", "a", "z") = "zbz"
     * 
     * StringUtil.replace("//?", "/", "_")         =   "__?"
     * StringUtil.replace(null, "/", "_")               =   null
     * StringUtil.replace("//?", "/", null)        =   "//?"
     * </pre>
     * 
     * ?:
     * 
     * <pre class="code">
     * StringUtil.replace("SH1265,SH5951", "([a-zA-Z]+[0-9]+)", "'$1'") = SH1265,SH5951
     * </pre>
     * 
     * (? {@link #replaceAll(CharSequence, String, String)} )
     * 
     * </blockquote>
     * 
     * <h3>?:</h3>
     * <blockquote>
     * <ol>
     * <li>??,, "b" ? "aaa"  "aa" ? "ba" ? "ab".</li>
     * <li>{@link java.util.regex.Matcher#replaceAll(String) Matcher.replaceAll()},
     * {@link java.util.regex.Matcher#quoteReplacement(String) Matcher.quoteReplacement()} ?</li>
     * </ol>
     * </blockquote>
     * 
     * @param text
     *            text to search and replace in, may be null
     * @param searchString
     *            the String to search for, may be null
     * @param replacement
     *            the String to replace it with, may be null
     * @return  <code>text</code> null, null<br>
     *          <code>searchString</code> null, <code>text</code><br>
     *          <code>replacement</code> null, <code>text</code><br>
     * @see java.lang.String#replace(CharSequence, CharSequence)
     * @see org.apache.commons.lang3.StringUtils#replace(String, String, String)
     * @since jdk 1.5
     */
    public static String replace(final String text, final String searchString, final String replacement) {
        return StringUtils.replace(text, searchString, replacement);
    }

    /**
     * <code>replacement</code>??? <code>regex</code>?.
     * 
     * <p>
     * ?, {@link java.util.regex.Matcher#replaceAll(String)},same as
     * <code>Pattern.compile(regex).matcher(str).replaceAll(repl)</code>
     * </p>
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * StringUtil.replaceAll("SH1265,SH5951,SH6766,SH7235,SH1265,SH5951,SH6766,SH7235", "([a-zA-Z]+[0-9]+)", "'$1'")
     * </pre>
     * 
     * <b>:</b>
     * 
     * <pre class="code">
     * 'SH1265','SH5951','SH6766','SH7235','SH1265','SH5951','SH6766','SH7235'
     * </pre>
     * 
     * </blockquote>
     * 
     * <h3>?:</h3>
     * 
     * <blockquote>
     * <p>
     * <code>replacement</code>, backslashes???(<tt>\</tt>) dollar signs? (<tt>$</tt>)????.
     * <br>
     * ? {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll};?,? {@link java.util.regex.Matcher#quoteReplacement
     * Matcher.quoteReplacement}??
     * <br>
     * Dollar signs may betreated as references to captured subsequences as described above,$,???,
     * $0?,$11?,$12?
     * <br>
     * andbackslashes are used to escape literal characters in the replacementstring.
     * </p>
     * </blockquote>
     * 
     * <h3>?:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * 
     * //?.
     * public void splitAndAddYinHao(){
     *     String a = "12345,56789,1123456";
     *     String[] aStrings = a.split(",");
     *     StringBuilder sb = new StringBuilder();
     *     int size = aStrings.length;
     *     for (int i = 0; i {@code <} size; i++){
     *         sb.append("'" + aStrings[i] + "'");
     *         if (i != size - 1){
     *             sb.append(",");
     *         }
     *     }
     *     LOGGER.debug(sb.toString());
     * }
     * 
     * </pre>
     * 
     * ???:
     * 
     * <pre class="code">
     * StringUtil.replaceAll("12345,56789,1123456", "([0-9]+)", "'$1'")
     * </pre>
     * 
     * :
     * 
     * <pre class="code">
     * '12345','56789','1123456'
     * </pre>
     * 
     * </blockquote>
     * 
     * @param content
     *            ??
     * @param regex
     *            ???
     * @param replacement
     *            ????
     * @return  <code>content</code> null, {@link StringUtils#EMPTY}<br>
     * @see <a href="http://stamen.iteye.com/blog/2028256">String?</a>
     * @see java.lang.String#replaceAll(String, String)
     * @since jdk 1.4
     */
    public static String replaceAll(CharSequence content, String regex, String replacement) {
        return null == content ? EMPTY : content.toString().replaceAll(regex, replacement);
    }

    /**
     *  <code>templateString</code> ?,???? .
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * String template = "/home/webuser/expressdelivery/${yearMonth}/${expressDeliveryType}/vipQuery_${fileName}.log";
     * Date date = new Date();
     * 
     * Map{@code <String, String>} valuesMap = new HashMap{@code <String, String>}();
     * valuesMap.put("yearMonth", DateUtil.toString(date, DatePattern.YEAR_AND_MONTH));
     * valuesMap.put("expressDeliveryType", "sf");
     * valuesMap.put("fileName", DateUtil.toString(date, DatePattern.TIMESTAMP));
     * LOGGER.debug(StringUtil.replace(template, valuesMap));
     * </pre>
     * 
     * <b>:</b>
     * 
     * <pre class="code">
     * /home/webuser/expressdelivery/2016-06/sf/vipQuery_20160608214846.log
     * </pre>
     * 
     * </blockquote>
     * 
     * <p>
     * ?:??,??el???
     * </p>
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * Map{@code <String, Object>} valuesMap = new HashMap{@code <String, Object>}();
     * valuesMap.put("today", DateUtil.toString(new Date(), COMMON_DATE));
     * valuesMap.put("user", new User(1L));
     * LOGGER.debug(StringUtil.replace("${today}${today1}${user.id}${user}", valuesMap) + "");
     * </pre>
     * 
     * <b>:</b>
     * 
     * <pre class="code">
     * 2016-07-16${today1}${user.id}com.feilong.test.User@16f9a31
     * </pre>
     * 
     * </blockquote>
     *
     * @param <V>
     *            the value type
     * @param templateString
     *            the template string
     * @param valuesMap
     *            the values map
     * @return  <code>templateString</code>  <code>StringUtils.isEmpty(templateString)</code>, {@link StringUtils#EMPTY}<br>
     *          <code>valuesMap</code> nullempty, <code>templateString</code><br>
     * @see org.apache.commons.lang3.text.StrSubstitutor#replace(String)
     * @see org.apache.commons.lang3.text.StrSubstitutor#replace(Object, Map)
     * @since 1.1.1
     */
    public static <V> String replace(CharSequence templateString, Map<String, V> valuesMap) {
        return StringUtils.isEmpty(templateString) ? EMPTY : StrSubstitutor.replace(templateString, valuesMap);
    }

    // [end]

    // [start]substring

    // ********************************substring************************************************
    /**
     * [?](<code>beginIndex</code>),.
     * 
     * <p>
     *  <code>beginIndex</code>,??,?,? {@link #substringLast(String, int)}
     * </p>
     *
     * <pre class="code">
     * StringUtil.substring(null, *)   = null
     * StringUtil.substring("", *)     = ""
     * StringUtil.substring("abc", 0)  = "abc"
     * StringUtil.substring("abc", 2)  = "c"
     * StringUtil.substring("abc", 4)  = ""
     * StringUtil.substring("abc", -2) = "bc"
     * StringUtil.substring("abc", -4) = "abc"
     * StringUtil.substring("jinxin.feilong",6)    =.feilong
     * </pre>
     * 
     * @param text
     *             the String to get the substring from, may be null
     * @param beginIndex
     *             the position to start from,negative means count back from the end of the String by this many characters
     * @return  <code>text</code> null, null<br>
     *         An empty ("") String  "".<br>
     * @see org.apache.commons.lang3.StringUtils#substring(String, int)
     * @see #substringLast(String, int)
     */
    public static String substring(final String text, final int beginIndex) {
        return StringUtils.substring(text, beginIndex);
    }

    /**
     * [?]?(<code>startIndex</code>),?(<code>length</code>).
     * 
     * <pre class="code">
     * StringUtil.substring(null, 6, 8)                 =   null
     * StringUtil.substring("jinxin.feilong", 6, 2)     =   .f
     * </pre>
     *
     * @param text
     *            ?
     * @param startIndex
     *            ?,0
     * @param length
     *             {@code >=1}
     * @return  <code>text</code> null, null<br>
     * @see org.apache.commons.lang3.StringUtils#substring(String, int, int)
     */
    public static String substring(final String text, int startIndex, int length) {
        return StringUtils.substring(text, startIndex, startIndex + length);
    }

    /**
     * [?]:??? <code>lastLenth</code> .
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * StringUtil.substringLast("jinxin.feilong", 5) = ilong
     * </pre>
     * 
     * </blockquote>
     * 
     * @param text
     *            
     * @param lastLenth
     *            ??
     * @return  <code>text</code> null, null<br>
     *          {@code lastLenth<0}, {@link StringUtils#EMPTY}<br>
     *          {@code text.length() <= lastLenth},text<br>
     *         ?<code> text.substring(text.length() - lastLenth)</code>
     * @see org.apache.commons.lang3.StringUtils#right(String, int)
     */
    public static String substringLast(final String text, int lastLenth) {
        return StringUtils.right(text, lastLenth);
    }

    /**
     * [?]:?? <code>lastLenth</code> .
     * 
     * <p>
     *  {@link java.lang.String#substring(int, int)}
     * </p>
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * StringUtil.substringWithoutLast("jinxin.feilong", 5) //jinxin.fe
     * </pre>
     * 
     * </blockquote>
     * 
     * @param text
     *            
     * @param lastLenth
     *            ??
     * @return  <code>text</code> null, {@link StringUtils#EMPTY}<br>
     * @see java.lang.String#substring(int, int)
     * @see org.apache.commons.lang3.StringUtils#left(String, int)
     */
    public static String substringWithoutLast(final String text, final int lastLenth) {
        return null == text ? EMPTY : text.substring(0, text.length() - lastLenth);
    }

    /**
     * [?]:? <code>lastString</code>.
     * 
     * <h3>:</h3>
     * 
     * <blockquote>
     * 
     * <pre class="code">
     * StringUtil.substringWithoutLast(null, "222")                     = ""
     * StringUtil.substringWithoutLast("jinxin.feilong", "ng")          = "jinxin.feilo"
     * StringUtil.substringWithoutLast("jinxin.feilong     ", "     ")  = "jinxin.feilong"
     * </pre>
     * 
     * </blockquote>
     *
     * @param text
     *            the text
     * @param lastString
     *            the last string
     * @return  <code>text</code> null, {@link StringUtils#EMPTY}<br>
     *          <code>lastString</code> null, <code>text.toString()</code><br>
     * @since 1.4.0
     */
    public static String substringWithoutLast(final CharSequence text, final String lastString) {
        if (null == text) {
            return EMPTY;
        }
        String textString = text.toString();
        if (null == lastString) {
            return textString;
        }
        return textString.endsWith(lastString) ? substringWithoutLast(textString, lastString.length()) : textString;
    }

    // [end]

    // [start]splitToT

    /**
     *  <code>value</code>  <code>regexSpliter</code> ? .
     * 
     * <p>
     *  {@link #tokenizeToStringArray(String, String)}  {@link StringUtils#split(String)}
     * </p>
     *
     * @param value
     *            value
     * @param regexSpliter
     *            ??,?,<b>.$|()[{^?*+\\</b> ?,.,<span style="color:red">"\"??"\\\\"</span> <br>
     *             {@link java.util.regex.Pattern#split(CharSequence)}
     * @return  <code>value</code> nullempty, {@link ArrayUtils#EMPTY_STRING_ARRAY}<br>
     * @see String#split(String)
     * @see String#split(String, int)
     * @see StringUtils#split(String)
     * @see java.util.regex.Pattern#split(CharSequence)
     */
    public static String[] split(String value, String regexSpliter) {
        return isNullOrEmpty(value) ? ArrayUtils.EMPTY_STRING_ARRAY : value.split(regexSpliter);
    }

    // [end]

    // [start]tokenizeToStringArray

    /**
     * ( {@link "org.springframework.util.StringUtils#tokenizeToStringArray"}).
     * 
     * <p>
     *  {@link #tokenizeToStringArray(String, String, boolean, boolean)},,? trimTokens = true;
     * ignoreEmptyTokens = true;
     * </p>
     * 
     * <h3>:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * String str = "jin.xin  feilong ,jinxin;venusdrogon;jim ";
     * String delimiters = ";, .";
     * String[] tokenizeToStringArray = StringUtil.tokenizeToStringArray(str, delimiters);
     * LOGGER.info(JsonUtil.format(tokenizeToStringArray));
     * </pre>
     * 
     * <b>:</b>
     * 
     * <pre class="code">
     * [
     * "jin",
     * "xin",
     * "feilong",
     * "jinxin",
     * "venusdrogon",
     * "jim"
     * ]
     * </pre>
     * 
     * </blockquote>
     * 
     * <p>
     * Tokenize the given String into a String array via a StringTokenizer. <br>
     * Trims tokens and omits empty tokens.
     * </p>
     * 
     * <p>
     * The given delimiters string is supposed to consist of any number of delimiter characters. Each of those characters can be used to
     * separate tokens. A delimiter is always a single character; for multi-character delimiters, consider using
     * <code>delimitedListToStringArray</code>
     * 
     * @param str
     *            the String to tokenize
     * @param delimiters
     *            the delimiter characters, assembled as String<br>
     *            ?,?? ";, " ,spring?/?
     * @return  <code>str</code> null, {@link ArrayUtils#EMPTY_STRING_ARRAY}<br>
     * @see java.util.StringTokenizer
     * @see String#trim()
     * @see "org.springframework.util.StringUtils#delimitedListToStringArray"
     * @see "org.springframework.util.StringUtils#tokenizeToStringArray"
     * 
     * @see #tokenizeToStringArray(String, String, boolean, boolean)
     * @since 1.0.7
     */
    public static String[] tokenizeToStringArray(String str, String delimiters) {
        boolean trimTokens = true;
        boolean ignoreEmptyTokens = true;
        return tokenizeToStringArray(str, delimiters, trimTokens, ignoreEmptyTokens);
    }

    /**
     * ( {@link "org.springframework.util.StringUtils#tokenizeToStringArray"}).
     * 
     * <p>
     * Tokenize the given String into a String array via a StringTokenizer.
     * </p>
     * 
     * <p>
     * The given delimiters string is supposed to consist of any number of delimiter characters. <br>
     * Each of those characters can be used to separate tokens. <br>
     * A delimiter is always a single character; <br>
     * for multi-character delimiters, consider using <code>delimitedListToStringArray</code>
     * </p>
     * 
     * <h3>about {@link StringTokenizer}:</h3>
     * 
     * <blockquote>
     * 
     * {@link StringTokenizer} implements {@code Enumeration<Object>}<br>
     *  Enumeration?, hasMoreTokens nextToken<br>
     * Enumeration? hasMoreElements nextElement, hasMoreTokens nextToken<br>
     * 
     * </blockquote>
     * 
     * @param str
     *            the String to tokenize
     * @param delimiters
     *            the delimiter characters, assembled as String<br>
     *            ?,?? ";, " ,spring?/?
     * @param trimTokens
     *            ? {@link String#trim()}?token
     * @param ignoreEmptyTokens
     *            ?token,true,token {@code >} 0;false?=0 <br>
     *            omit empty tokens from the result array
     *            (only applies to tokens that are empty after trimming; StringTokenizer
     *            will not consider subsequent delimiters as token in the first place).
     * @return  <code>str</code> null, {@link ArrayUtils#EMPTY_STRING_ARRAY}<br>
     * @see java.util.StringTokenizer
     * @see String#trim()
     * @see "org.springframework.util.StringUtils#delimitedListToStringArray"
     * @see "org.springframework.util.StringUtils#tokenizeToStringArray"
     * @since 1.0.7
     */
    public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens,
            boolean ignoreEmptyTokens) {
        if (null == str) {
            return ArrayUtils.EMPTY_STRING_ARRAY;
        }

        StringTokenizer stringTokenizer = new StringTokenizer(str, delimiters);
        List<String> tokens = new ArrayList<String>();
        while (stringTokenizer.hasMoreTokens()) {
            String token = stringTokenizer.nextToken();
            token = trimTokens ? token.trim() : token;//

            if (!ignoreEmptyTokens || token.length() > 0) {
                tokens.add(token);
            }
        }
        return ConvertUtil.toArray(tokens, String.class);
    }

    // [end]

    // [start]format

    /**
     * ?.
     * 
     * <h3>:</h3>
     * <blockquote>
     * <ol>
     * <li>%index$,index1?,index???.</li>
     * <li>?:?4?:%[index$][][?]??</li>
     * <li>StringUtil.format("%03d", 1) ?? StringUtil.format("%03d", "1")</li>
     * <li>?:%[index$][][][.]??</li>
     * </ol>
     * </blockquote>
     * 
     * <p>
     * ?:
     * </p>
     * 
     * <h3>?</h3>
     * 
     * <blockquote>
     * <table border="1" cellspacing="0" cellpadding="4" summary="">
     * <tr style="background-color:#ccccff">
     * <th align="left">?</th>
     * <th align="left"></th>
     * <th align="left"></th>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%s</td>
     * <td></td>
     * <td>"mingrisoft"</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%c</td>
     * <td></td>
     * <td>'m'</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%b</td>
     * <td></td>
     * <td>true</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%d</td>
     * <td>(??)</td>
     * <td>99</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%x</td>
     * <td>(??)</td>
     * <td>FF</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%o</td>
     * <td>()</td>
     * <td>77</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%f</td>
     * <td></td>
     * <td>99.99</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%a</td>
     * <td>??</td>
     * <td>FF.35AE</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%e</td>
     * <td></td>
     * <td>9.38e+5</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%g</td>
     * <td>(fe)</td>
     * <td></td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%h</td>
     * <td>?</td>
     * <td></td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%%</td>
     * <td></td>
     * <td></td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>%n</td>
     * <td>?</td>
     * <td></td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>%tx</td>
     * <td>(x???</td>
     * <td></td>
     * </tr>
     * </table>
     * </blockquote>
     * 
     * <h3></h3>
     * 
     * <blockquote>
     * <table border="1" cellspacing="0" cellpadding="4" summary="">
     * <tr style="background-color:#ccccff">
     * <th align="left"></th>
     * <th align="left"></th>
     * <th align="left"></th>
     * <th align="left"></th>
     * </tr>
     * 
     * <tr valign="top">
     * <td>+</td>
     * <td>?</td>
     * <td>("%+d",15)</td>
     * <td>+15</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>-</td>
     * <td>?(??"0"?)</td>
     * <td>("%-5d",15)</td>
     * <td>|15 |</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>0</td>
     * <td>??0</td>
     * <td>("%04d", 99)</td>
     * <td>0099</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td></td>
     * <td>??</td>
     * <td>("% 4d", 99)</td>
     * <td>| 99|</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>,</td>
     * <td>","</td>
     * <td>("%,f", 9999.99)</td>
     * <td>9,999.990000</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>(</td>
     * <td>??</td>
     * <td>("%(f", -99.99)</td>
     * <td>(99.990000)</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>#</td>
     * <td>??,1680x0</td>
     * <td>("%#x", 99) <br>
     * ("%#o", 99)</td>
     * <td>0x63<br>
     * 0143</td>
     * </tr>
     * 
     * <tr valign="top" style="background-color:#eeeeff">
     * <td>{@code <}</td>
     * <td>??????</td>
     * <td>("%f%{@code <}3.2f", 99.45)</td>
     * <td>99.45000099.45</td>
     * </tr>
     * 
     * <tr valign="top">
     * <td>$</td>
     * <td>??</td>
     * <td>("%1$d,%2$s", 99,"abc")</td>
     * <td>99,abc</td>
     * </tr>
     * 
     * </table>
     * </blockquote>
     * 
     * @param format
     *            the format
     * @param args
     *            the args
     * @return  <code>format</code> null, {@link StringUtils#EMPTY}<br>
     *         ? {@link String#format(String, Object...)}
     * @see java.util.Formatter
     * @see String#format(String, Object...)
     * @see String#format(java.util.Locale, String, Object...)
     * @since JDK 1.5
     */
    public static String format(String format, Object... args) {
        return null == format ? EMPTY : String.format(format, args);
    }
    // [end]
}