com.feilong.commons.core.util.StringUtil.java Source code

Java tutorial

Introduction

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

Source

/*
 * Copyright (C) 2008 feilong (venusdrogon@163.com)
 *
 * 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.commons.core.util;

import java.io.UnsupportedEncodingException;
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.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.feilong.commons.core.bean.BeanUtil;
import com.feilong.commons.core.bean.BeanUtilException;
import com.feilong.commons.core.io.CharsetType;
import com.feilong.commons.core.lang.ObjectUtil;

/**
 * StringUtil {@link String},? ,?,format,?16?.
 * 
 * <h3>(split)</h3>
 * 
 * <blockquote>
 * <ul>
 * <li>{@link #splitToTArray(String, String, Class)}</li>
 * <li>{@link #splitToStringArray(String, String)}</li>
 * <li>{@link #splitToIntegerArray(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>
 * </blockquote>
 * 
 * ,split  ? {@link Pattern#split(CharSequence)} (?, $|()[{^?*+\\ ???), {@link StringTokenizer} ,
 * StringTokenizer<br>
 * ,?,{@link StringTokenizer}
 * 
 * @author  2010-2-9 ?09:53:37
 * @see "org.springframework.util.StringUtils#tokenizeToStringArray(String, String)"
 * @see "org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#MULTI_VALUE_ATTRIBUTE_DELIMITERS"
 * @see java.util.StringTokenizer
 * @see org.apache.commons.lang3.StringUtils
 * @since 1.0.0
 */
public final class StringUtil {

    /** The Constant log. */
    private static final Logger log = LoggerFactory.getLogger(StringUtil.class);

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

    // [start] search

    /**
     * ?  
     * 
     * <pre>
     *  StringUtil.searchTimes("xin", "xin")
     *  return  1
     *  
     * StringUtil.searchTimes("xiiiin", "ii")
     *  return  2
     * 
     * </pre>
     *
     * @param source
     *            ?
     * @param target
     *            ?
     * @return count of target string in source
     * @see org.apache.commons.lang3.StringUtils#countMatches(CharSequence, CharSequence)
     * @since 1.0.2
     * @deprecated  {@link org.apache.commons.lang3.StringUtils#countMatches(CharSequence, CharSequence)}
     */
    @Deprecated
    public static int searchTimes(String source, String target) {
        if (null == source) {
            throw new IllegalArgumentException("source can't be null!");
        }
        if (null == target) {
            throw new IllegalArgumentException("target can't be null!");
        }

        // times 
        int count = 0;

        // while  
        int j = 0;

        // ??
        int fromIndex = 0;

        int sourceLength = source.length();
        int targetLength = target.length();

        //  0
        while (j != sourceLength) {

            //  ?
            int i = source.indexOf(target, fromIndex);
            if (i != -1) {

                // ? , 
                //    
                j = i + targetLength;

                fromIndex = i + targetLength;

                //  ++
                count++;
            } else {
                // ?? 
                break;
            }
        }
        return count;
    }

    // [end]
    /**
     * ???<br>
     * 
     * <pre>
     * String text = &quot;jinxin.feilong&quot;;
     * log.info(StringUtil.addDoubleQuotes(text));
     * 
     * :  "jinxin.feilong"
     * </pre>
     * 
     * @param text
     *            ?
     * @return "\"" + text + "\""
     */
    public static String addDoubleQuotes(String text) {
        return "\"" + text + "\"";
    }

    /**
     * ?<br>
     * 
     * <pre>
     * StringUtil.join(true, &quot;_&quot;, &quot;a&quot;, &quot;2&quot;)
     * 
     * return a_2
     * </pre>
     * 
     * @param isJoinBlankOrNull
     *            ?null,true 
     * @param separator
     *            
     * @param elements
     *            ?
     * @return the string
     */
    public static final String join(boolean isJoinBlankOrNull, String separator, String... elements) {
        if (Validator.isNullOrEmpty(elements)) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        int length = elements.length;
        for (int i = 0; i < length; ++i) {
            String string = elements[i];
            boolean isCanJoin = true;
            //  null ? ?
            if (Validator.isNullOrEmpty(string) && !isJoinBlankOrNull) {
                isCanJoin = false;
            }
            if (isCanJoin) {
                // ????
                if (stringBuilder.length() > 0) {
                    stringBuilder.append(separator);
                }
                stringBuilder.append(string);
            }
        }
        return stringBuilder.toString();
    }

    /**
     * ??? jinxin
     * 
     * return Jinxin
     * 
     * <pre>
     * StringUtils.capitalize(null)  = null
     * StringUtils.capitalize(&quot;&quot;)    = &quot;&quot;
     * StringUtils.capitalize(&quot;cat&quot;) = &quot;Cat&quot;
     * StringUtils.capitalize(&quot;cAt&quot;) = &quot;CAt&quot;
     * </pre>
     * 
     * @param word
     *            ??
     * @return ???
     * @see org.apache.commons.lang3.StringUtils#swapCase(String)
     * @see org.apache.commons.lang3.StringUtils#capitalize(String)
     */
    public static final String firstCharToUpperCase(String word) {
        return StringUtils.capitalize(word);
    }

    /**
     * ???? Jinxin
     * 
     * return jinxin
     * 
     * <pre>
     * StringUtils.capitalize(null)  = null
     * StringUtils.capitalize(&quot;&quot;)    = &quot;&quot;
     * StringUtils.capitalize(&quot;Jinxin&quot;) = &quot;jinxin&quot;
     * StringUtils.capitalize(&quot;CAt&quot;) = &quot;cAt&quot;
     * </pre>
     * 
     * @param word
     *            ??
     * @return ????
     * @see org.apache.commons.lang3.StringUtils#uncapitalize(String)
     */
    public static final String firstCharToLowerCase(String word) {
        return StringUtils.uncapitalize(word);
    }

    // [start]Contain

    /**
     * ???.
     * 
     * @param text
     *             jinxin,?string
     * @param beIncludedString
     *            ? in
     * @return ?true,text null false
     * @see String#indexOf(String)
     */
    public static final boolean isContain(Object text, String beIncludedString) {
        if (null == text) {
            log.warn("the param \"text\" is null,default return false");
            return false;
        }
        int indexOf = text.toString().indexOf(beIncludedString);
        return indexOf != -1;
    }

    /**
     *  ? ??<br>
     * 
     * <pre>
     * StringUtil.isContainIgnoreCase(null, &quot;&quot;)  return false
     * StringUtil.isContainIgnoreCase(text, null) return false
     * StringUtil.isContainIgnoreCase(text, &quot;&quot;) return true
     * StringUtil.isContainIgnoreCase(text, &quot;feilong&quot;) return true
     * StringUtil.isContainIgnoreCase(text, &quot;feilong1&quot;)  return false
     * StringUtil.isContainIgnoreCase(text, &quot;feiLong&quot;)  return true
     * 
     * </pre>
     * 
     * @param text
     *            the text
     * @param beIncludedString
     *            the be included string
     * @return <ul>
     *         <li> null==text, return false</li>
     *         <li> null==beIncludedString, return false</li>
     *         <li> ? ? ,??</li>
     *         </ul>
     */
    public static final boolean isContainIgnoreCase(Object text, String beIncludedString) {
        if (null == text) {
            log.warn("the param \"text\" is null,default return false");
            return false;
        }
        if (null == beIncludedString) {
            log.warn("the param \"beIncludedString\" is null,default return false");
            return false;
        }
        return isContain(text.toString().toLowerCase(), beIncludedString.toLowerCase());
    }

    // [end] 

    // [start]replace

    // ********************************replace************************************************
    /**
     *  replacement ????..
     * 
     * @param content
     *            ??
     * @param regex
     *            ???
     * @param replacement
     *            ????
     * @return String,?,""
     */
    public static final String replaceAll(Object content, String regex, String replacement) {
        if (null == content) {
            return "";
        }
        return content.toString().replaceAll(regex, replacement);
    }

    /**
     * ????????.<br>
     * ?? "b" ? "aaa"  "aa" ? "ba" ? "ab".
     * 
     * <pre>
     * ?replacement
     * </pre>
     * 
     * .
     * 
     * @param content
     *            
     * @param target
     *            ?? char ?
     * @param replacement
     *            char ??
     * @return ????
     */
    public static final String replace(Object content, String target, Object replacement) {
        if (null == content) {
            return "";
        }
        // ??null
        if (Validator.isNullOrEmpty(replacement)) {
            replacement = "";
        }
        return content.toString().replace(target, replacement.toString());
    }

    /**
     *  <code>content</code> ?? <code>target</code> ?? <code>bean</code>? <code>filedName</code> .
     *
     * @param content
     *            
     * @param target
     *            ??
     * @param bean
     *            bean
     * @param filedName
     *            ??
     * @return ?,content ??target ??bean?filedName
     * @throws BeanUtilException
     *             the bean util exception
     */
    public static final String replace(Object content, String target, Object bean, String filedName)
            throws BeanUtilException {
        String replacement = "";
        // ??null
        if (Validator.isNotNullOrEmpty(bean)) {
            Object filedValue = BeanUtil.getProperty(bean, filedName);
            if (null != filedValue) {
                replacement = filedValue.toString();
            }
        }
        return replace(content, target, replacement);
    }

    /**
     * * The following example demonstrates this:
     * 
     * <pre>
     * Map valuesMap = HashMap();
     * valuesMap.put(&quot;animal&quot;, &quot;quick brown fox&quot;);
     * valuesMap.put(&quot;target&quot;, &quot;lazy dog&quot;);
     * String templateString = &quot;The ${animal} jumped over the ${target}.&quot;;
     * StrSubstitutor sub = new StrSubstitutor(valuesMap);
     * String resolvedString = sub.replace(templateString);
     * </pre>
     * 
     * yielding:
     * 
     * <pre>
     *      The quick brown fox jumped over the lazy dog.
     * </pre>
     *
     * @param <V>
     *            the value type
     * @param templateString
     *            the template string
     * @param valuesMap
     *            the values map
     * @return the string
     * @see org.apache.commons.lang3.text.StrSubstitutor
     * @since 1.1.1
     */
    public static final <V> String replace(String templateString, Map<String, V> valuesMap) {
        StrSubstitutor strSubstitutor = new StrSubstitutor(valuesMap);
        String resolvedString = strSubstitutor.replace(templateString);
        return resolvedString;
    }

    // [end]

    // [start]startsWith

    /**
     * ??..
     * 
     * @param value
     *            value
     * @param prefix
     *            ?
     * @return ???? true? false.??? String  equals(Object)  true.
     */
    public static final boolean startsWith(Object value, String prefix) {
        return ObjectUtil.toString(value).startsWith(prefix);
    }

    // [end]
    /**
     * (???).
     * 
     * @param str
     *            
     * @param i
     *            
     * @return (???)
     */
    //TODO +javadoc
    public static final String stringAddInt(String str, int i) {
        int length = str.length();
        String pattern = "";
        for (int j = 0; j < length; ++j) {
            pattern += "0";
        }
        return NumberUtil.toString(Integer.parseInt(str) + i, pattern);
    }

    // [start]substring

    // ********************************substring************************************************
    /**
     * [?](beginIndex). <br>
     * text.substring(beginIndex)
     * 
     * <pre>
     * substring("jinxin.feilong",6) 
     * 
     * return .feilong
     * </pre>
     * 
     * @param text
     *            
     * @param beginIndex
     *            
     * @return <ul>
     *         <li> Validator.isNull(t),return null</li>
     *         <li>else,return text.substring(beginIndex)</li>
     *         </ul>
     */
    public static final String substring(Object text, int beginIndex) {
        String t = ObjectUtil.toString(text);
        if (Validator.isNullOrEmpty(t)) {
            return null;
        }
        return t.substring(beginIndex);
    }

    /**
     * [?]?(startIndex),?(length)<br>
     * 
     * <pre>
     * StringUtil.substring("jinxin.feilong", 6, 2)
     * 
     * renturn .f
     * </pre>
     * 
     * @param textObject
     *            ?
     * @param startIndex
     *            ?,0
     * @param length
     *             {@code >=1} 1 ? <br>
     *            ,??
     * @return
     *         <pre>
     * {@code
     *       Validator.isNullOrEmpty(textValue),   return null
     *       startIndex>textLength - 1,         return null
     *       startIndex==textLength - 1,         return substringLast(textString, 1)
     *       length<1,                     return null
     *       1 == length,                     return textString.substring(startIndex, startIndex + 1)
     *       remainLength > length,            return textString.substring(startIndex, startIndex + length)
     *       remainLength <= length,            return textString.substring(startIndex)
     * }
     * </pre>
     */
    public static final String substring(Object textObject, int startIndex, int length) {
        String returnValue = null;
        if (Validator.isNullOrEmpty(textObject)) {
            return null;
        }
        String textString = ObjectUtil.toString(textObject);
        int textLength = textString.length();
        // ??
        if (startIndex > textLength - 1) {
            return null;
        } else if (startIndex == textLength - 1) {// ??
            return substringLast(textString, 1);
        } else if (length < 1) {// ?>=1
            return null;
        } else if (1 == length) {// ?1 ?
            // ??
            return textString.substring(startIndex, startIndex + 1);
        } else {
            // ??
            int remainLength = textLength - startIndex;
            // ?
            if (remainLength > length) {
                // ?
                int endIndex = startIndex + length;
                // ???
                returnValue = textString.substring(startIndex, endIndex);
            } else {
                // ??
                returnValue = textString.substring(startIndex);
            }
        }
        return returnValue;
    }

    /**
     * [?]:{@link #substring(String, String, int)},  shift=0
     * 
     * <pre>
     * substring(&quot;jinxin.feilong&quot;,&quot;.&quot;)======&gt;&quot;.feilong&quot;
     * </pre>
     * 
     * @param text
     *            text
     * @param beginString
     *            beginString?
     * @return {@link #substring(String, String, int)},  shift=0
     */
    public static final String substring(String text, String beginString) {
        return substring(text, beginString, 0);
    }

    /**
     * [?]:?(?)??,shift?????,<br>
     * beginIndex= text.indexOf(beginString) + shift;<br>
     * return text.substring(beginIndex);
     * 
     * <pre>
     * substring(&quot;jinxin.feilong&quot;,&quot;.&quot;,0)======&gt;&quot;.feilong&quot;
     * substring(&quot;jinxin.feilong&quot;,&quot;.&quot;,1)======&gt;&quot;feilong&quot;
     * </pre>
     * 
     * @param text
     *            text
     * @param beginString
     *            beginString
     * @param shift
     *            ??,??,0??
     * @return <ul>
     *         <li>if isNullOrEmpty(text),return null</li>
     *         <li>if isNullOrEmpty(beginString),return null</li>
     *         <li>if text.indexOf(beginString)==-1,return null</li>
     *         <li>{@code  beginIndex + shift > text.length()},return null</li>
     *         <li>else,return text.substring(beginIndex + shift)</li>
     *         </ul>
     * @throws IllegalArgumentException
     *             {@code  if beginIndex + shift<0}
     * 
     */
    public static final String substring(String text, String beginString, int shift)
            throws IllegalArgumentException {
        if (Validator.isNullOrEmpty(text)) {
            return null;
        } else if (Validator.isNullOrEmpty(beginString)) {
            return null;
        }
        //****************************************************
        int beginIndex = text.indexOf(beginString);
        // ?
        if (beginIndex == -1) {
            return null;
        }
        //****************************************************
        int startIndex = beginIndex + shift;
        if (startIndex < 0) {
            String logInfo = StringBuilderUtil.append("beginIndex + shift <0,", "beginIndex:", beginIndex,
                    ",shift:" + shift, ",text:" + text, ",text.length:", text.length());

            throw new IllegalArgumentException(logInfo);
        } else if (startIndex > text.length()) {

            if (log.isInfoEnabled()) {
                String logInfo = StringBuilderUtil.append("beginIndex + shift > text.length(),", "beginIndex:",
                        beginIndex, ",shift:" + shift, ",text:" + text, ",text.length:", text.length());
                log.info(logInfo);
            }

            return null;
        }
        // 0 
        return text.substring(startIndex);
    }

    /**
     * [?]:?(startString),???endString.
     * 
     * @param text
     *            
     * @param startString
     *            ,null?
     * @param endString
     *            ?
     * @return <pre>
     * Validator.isNull(text),return null;
     * Validator.isNull(startString),return text.substring(0, text.indexOf(endString))
     * 
     * </pre>
     */
    public static final String substring(String text, String startString, String endString) {
        if (Validator.isNullOrEmpty(text)) {
            return null;
        } else if (Validator.isNullOrEmpty(startString)) {
            return text.substring(0, text.indexOf(endString));
        }
        int beginIndex = text.indexOf(startString);
        int endIndex = text.indexOf(endString);
        return text.substring(beginIndex, endIndex);
    }

    /**
     * [?]:??.
     * 
     * @param text
     *            
     * @param lastLenth
     *            ??
     * @return ??
     */
    public static final String substringLast(String text, int lastLenth) {
        return text.substring(text.length() - lastLenth);
    }

    /**
     * [?]:??.
     * 
     * @param text
     *            
     * @param lastLenth
     *            ??
     * @return ??,text,""
     */
    public static final String substringWithoutLast(String text, int lastLenth) {
        if (Validator.isNullOrEmpty(text)) {
            return null;
        }
        return text.substring(0, text.length() - lastLenth);
    }

    // [end]

    // [start]toBytes

    // ********************************************************************************
    /**
     * ??byte.
     * 
     * @param value
     *            
     * @return byte
     */
    public static final byte[] toBytes(String value) {
        return value.getBytes();
    }

    /**
     * ??byte.
     * 
     * @param value
     *            
     * @param charsetName
     *            ?? charset ??, utf-8, {@link CharsetType}
     * @return  byte 
     * @see String#getBytes(String)
     * @see CharsetType
     */
    public static final byte[] toBytes(String value, String charsetName) {
        try {
            return value.getBytes(charsetName);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getClass().getName(), e);
        }
        return null;
    }

    // [end]
    /**
     * string ?,???.
     * 
     * @param <T>
     *            the generic type
     * @param value
     *            
     * @param class1
     *            the class1
     * @return <pre>
     * if (class1 == String.class){
     *     return (T) value;
     * }else if (class1 == Boolean.class){
     *     return (T) ObjectUtil.objectToBoolean(value);
     * }else if (class1 == Integer.class){
     *     return (T) ObjectUtil.objectToInteger(value);
     * }
     * </pre>
     */
    @SuppressWarnings("unchecked")
    public static final <T> T toT(String value, Class<?> class1) {
        return (T) ObjectUtil.toT(value, class1);
    }

    // [start]splitToT

    /**
     * ? .
     * 
     * @param value
     *            value
     * @param regexSpliter
     *            ,????, .$|()[{^?*+\\ ??.,<br>
     *            ??"\"??"\\\\"<br>
     *             {@link java.util.regex.Pattern#split(CharSequence)}
     * @return value null,null
     * @see String#split(String)
     * @see String#split(String, int)
     * @see java.util.regex.Pattern#split(CharSequence)
     */
    public static final String[] splitToStringArray(String value, String regexSpliter) {
        if (null != value) {
            String[] strings = value.split(regexSpliter);
            return strings;
        }
        return null;
    }

    /**
     * ? .
     * 
     * @param value
     *            value
     * @param regexSpliter
     *            ,????, .$|()[{^?*+\\ ??.,<br>
     *            ??"\"??"\\\\"<br>
     *             {@link java.util.regex.Pattern#split(CharSequence)}
     * @return value null,null
     * @see String#split(String)
     * @see String#split(String, int)
     * @see ArrayUtil#toIntegers(Object[])
     * @see java.util.regex.Pattern#split(CharSequence)
     */
    public static final Integer[] splitToIntegerArray(String value, String regexSpliter) {
        if (null != value) {
            String[] strings = value.split(regexSpliter);
            return ArrayUtil.toIntegers(strings);
        }
        return null;
    }

    /**
     * ?T.
     * 
     * @param <T>
     *            the generic type
     * @param value
     *            
     * @param regexSpliter
     *            ,????, .$|()[{^?*+\\ ??.,<br>
     *            ??"\"??"\\\\"<br>
     *             {@link java.util.regex.Pattern#split(CharSequence)}
     * @param typeClass
     *            , T <br>
     *            Temp support only:String.class and Integer.class
     * @return 
     * @throws IllegalArgumentException
     *             ??String Integer?,
     * @see java.util.regex.Pattern#split(CharSequence)
     * @see #splitToIntegerArray(String, String)
     * @see #splitToStringArray(String, String)
     */
    @SuppressWarnings("unchecked")
    public static final <T> T[] splitToTArray(String value, String regexSpliter, Class<?> typeClass)
            throws IllegalArgumentException {
        if (typeClass == String.class) {
            return (T[]) splitToStringArray(value, regexSpliter);
        } else if (typeClass == Integer.class) {
            return (T[]) splitToIntegerArray(value, regexSpliter);
        }
        throw new IllegalArgumentException(
                "Param typeClass don't support,Temp support only:String.class and Integer.class");
    }

    // [end]

    // [start]tokenizeToStringArray

    /**
     * ( {@link "org.springframework.util.StringUtils#tokenizeToStringArray"})<br>
     * Tokenize the given String into a String array via a StringTokenizer.
     * Trims tokens and omits empty tokens.
     * <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}
     * 
     * @param str
     *            the String to tokenize
     * @param delimiters
     *            the delimiter characters, assembled as String<br>
     *            ?,?? ";, " ,spring?/?
     * @return an array of the tokens
     * @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 = true;
        boolean ignoreEmptyTokens = true;
        return tokenizeToStringArray(str, delimiters, trimTokens, ignoreEmptyTokens);
    }

    /**
     * ( {@link "org.springframework.util.StringUtils#tokenizeToStringArray"})<br>
     * Tokenize the given String into a String array via a StringTokenizer.
     * <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}
     * 
     * @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>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 an array of the tokens ({@code null} if the input String
     *         was {@code null})
     * @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 (str == null) {
            return null;
        }

        //StringTokenizer implements Enumeration<Object>
        // Enumeration?,   hasMoreTokens nextToken
        //Enumeration?  hasMoreElements nextElement   hasMoreTokens nextToken
        StringTokenizer st = new StringTokenizer(str, delimiters);
        List<String> tokens = new ArrayList<String>();
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            if (trimTokens) {
                token = token.trim();
            }
            if (!ignoreEmptyTokens || token.length() > 0) {
                tokens.add(token);
            }
        }
        return CollectionsUtil.toArray(tokens);
    }

    // [end]
    // [start]format

    /**
     * ?
     * <ul>
     * <li>StringUtil.format("%03d", 1)?? StringUtil.format("%03d", "1")</li>
     * </ul>
     * %index$index1?index???.<br>
     * ?:?4?:%[index$][][?]??<br>
     * ?:%[index$][][][.]??<br>
     * ?? ?<br>
     * 
     * <h3>?</h3>
     * 
     * <pre>
     * %s      "mingrisoft"
     * %c      'm'
     * %b      true
     * %d   ??   99
     * %x   ??   FF
     * %o      77
     * %f      99.99
     * %a   ??   FF.35AE
     * %e      9.38e+5
     * %g   fe
     * %h   ?
     * %%      
     * %n   ?
     * %tx   x???
     * </pre>
     * 
     * <h3></h3>
     * 
     * <pre>
     * {@code
     * +   ?   ("%+d",15)   +15
     * -   ?   ("%-5d",15)   |15   |  ??0??
     * 0   ??0   ("%04d", 99)   0099
     *    ??   ("% 4d", 99)   |  99|
     * ,   ,?   ("%,f", 9999.99)   9,999.990000
     * (   ??   ("%(f", -99.99)   (99.990000)
     * #   ??1680x0
     * <   ??????   ("%f%<3.2f", 99.45)   99.45000099.45
     * $   ??   ("%1$d,%2$s", 99,"abc")   99,abc
     * }
     * </pre>
     * 
     * @param format
     *            the format
     * @param args
     *            the args
     * @return A formatted string
     * @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 String.format(format, args);
    }

    // [end]

    // [start]toHexStringUpperCase/toOriginal

    /**
     *  ? HexString ?gdpglc?.
     * 
     * @param original
     *            
     * @return the string
     */
    public static final String toHexStringUpperCase(String original) {
        //  Charset.defaultCharset()   ISO-8859-1
        String hexStringUpperCase = ByteUtil.bytesToHexStringUpperCase(original.getBytes());
        log.debug("original:{},hexStringUpperCase:{}", original, hexStringUpperCase);
        return hexStringUpperCase;
    }

    /**
     *  ? HexString ?gdpglc?.
     * 
     * @param original
     *            
     * @param charsetName
     *             {@link CharsetType}
     * @return the string
     */
    public static final String toHexStringUpperCase(String original, String charsetName) {
        try {
            String hexStringUpperCase = ByteUtil.bytesToHexStringUpperCase(original.getBytes(charsetName));
            log.debug("original:{},hexStringUpperCase:{}", original, hexStringUpperCase);
            return hexStringUpperCase;
        } catch (UnsupportedEncodingException e) {
            log.error(e.getClass().getName(), e);
        }
        return null;
    }

    /**
     *  ? HexString.
     * 
     * @param hexStringUpperCase
     *            HexString
     * @return the string
     */
    public static final String toOriginal(String hexStringUpperCase) {
        byte[] hexBytesToBytes = ByteUtil.hexBytesToBytes(hexStringUpperCase.getBytes());
        String original = new String(hexBytesToBytes);
        log.debug("hexStringUpperCase:{},original:{}", hexStringUpperCase, original);
        return original;
    }

    /**
     *  ? HexString.
     * 
     * @param hexStringUpperCase
     *            the hex string upper case
     * @param charsetName
     *            
     * @return the string
     */
    public static final String toOriginal(String hexStringUpperCase, String charsetName) {
        byte[] hexBytesToBytes = ByteUtil.hexBytesToBytes(hexStringUpperCase.getBytes());
        String original = null;
        try {
            original = new String(hexBytesToBytes, charsetName);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getClass().getName(), e);
        }
        log.debug("hexStringUpperCase:{},original:{}", hexStringUpperCase, original);
        return original;
    }

    // [end]
}