All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jetbrick.util.StringUtils Maven / Gradle / Ivy

/**
 * Copyright 2013-2016 Guoqiang Chen, Shanghai, China. All rights reserved.
 *
 *   Author: Guoqiang Chen
 *    Email: [email protected]
 *   WebURL: https://github.com/subchen
 *
 * 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 jetbrick.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

public final class StringUtils {

    // Empty checks
    // -----------------------------------------------------------------------
    /**
     * 

* Checks if a String is empty ("") or null. *

* *
     * StringUtils.isEmpty(null)      = true
     * StringUtils.isEmpty("")        = true
     * StringUtils.isEmpty(" ")       = false
     * StringUtils.isEmpty("bob")     = false
     * StringUtils.isEmpty("  bob  ") = false
     * 
*/ public static boolean isEmpty(final String s) { return s == null || s.length() == 0; } /** *

* Checks if a String is not empty ("") and not null. *

* *
     * StringUtils.isNotEmpty(null)      = false
     * StringUtils.isNotEmpty("")        = false
     * StringUtils.isNotEmpty(" ")       = true
     * StringUtils.isNotEmpty("bob")     = true
     * StringUtils.isNotEmpty("  bob  ") = true
     * 
*/ public static boolean isNotEmpty(final String s) { return s != null && s.length() > 0; } /** *

* Checks if a String is whitespace, empty ("") or null. *

* *
     * StringUtils.isBlank(null)      = true
     * StringUtils.isBlank("")        = true
     * StringUtils.isBlank(" ")       = true
     * StringUtils.isBlank("bob")     = false
     * StringUtils.isBlank("  bob  ") = false
     * 
*/ public static boolean isBlank(final String s) { int len; if (s == null || (len = s.length()) == 0) { return true; } for (int i = 0; i < len; i++) { if (Character.isWhitespace(s.charAt(i)) == false) { return false; } } return true; } /** *

* Checks if a String is not empty (""), not null and not whitespace * only. *

* *
     * StringUtils.isNotBlank(null)      = false
     * StringUtils.isNotBlank("")        = false
     * StringUtils.isNotBlank(" ")       = false
     * StringUtils.isNotBlank("bob")     = true
     * StringUtils.isNotBlank("  bob  ") = true
     * 
*/ public static boolean isNotBlank(final String s) { return !isBlank(s); } public static byte[] getBytes(String s, String charsetName) { if (s == null) { return null; } try { return s.getBytes(charsetName); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public static byte[] getUtf8Bytes(String s) { return s.getBytes(CharsetUtils.UTF_8); } // Trim // ----------------------------------------------------------------------- /** *

* Removes control characters (char <= 32) from both ends of this String, * handling {@code null} by returning {@code null}. *

* *

* The String is trimmed using {@link String#trim()}. Trim removes start and * end characters <= 32. *

* *
     * StringUtils.trim(null)          = null
     * StringUtils.trim("")            = ""
     * StringUtils.trim("     ")       = ""
     * StringUtils.trim("abc")         = "abc"
     * StringUtils.trim("    abc    ") = "abc"
     * 
*/ public static String trim(final String s) { return s == null ? null : s.trim(); } /** *

* Removes control characters (char <= 32) from both ends of this String * returning {@code null} if the String is empty ("") after the trim or if * it is {@code null}. * *

* The String is trimmed using {@link String#trim()}. Trim removes start and * end characters <= 32. *

* *
     * StringUtils.trimToNull(null)          = null
     * StringUtils.trimToNull("")            = null
     * StringUtils.trimToNull("     ")       = null
     * StringUtils.trimToNull("abc")         = "abc"
     * StringUtils.trimToNull("    abc    ") = "abc"
     * 
*/ public static String trimToNull(final String s) { final String ts = trim(s); return ts == null || ts.length() == 0 ? null : ts; } /** *

* Removes control characters (char <= 32) from both ends of this String * returning an empty String ("") if the String is empty ("") after the trim * or if it is {@code null}. * *

* The String is trimmed using {@link String#trim()}. Trim removes start and * end characters <= 32. *

* *
     * StringUtils.trimToEmpty(null)          = ""
     * StringUtils.trimToEmpty("")            = ""
     * StringUtils.trimToEmpty("     ")       = ""
     * StringUtils.trimToEmpty("abc")         = "abc"
     * StringUtils.trimToEmpty("    abc    ") = "abc"
     * 
*/ public static String trimToEmpty(final String s) { return s == null ? "" : s.trim(); } public static String[] trim(String[] ss) { if (ss != null) { for (int i = 0; i < ss.length; i++) { String string = ss[i]; if (string != null) { ss[i] = string.trim(); } } } return ss; } // Defaults // ----------------------------------------------------------------------- /** *

* Returns either the passed in String, or if the String is {@code null}, * the value of {@code defaultStr}. *

* *
     * StringUtils.defaultIfNull(null, "NULL")  = "NULL"
     * StringUtils.defaultIfNull("", "NULL")    = ""
     * StringUtils.defaultIfNull("bat", "NULL") = "bat"
     * 
*/ public static String defaultIfNull(final String s, final String defaultStr) { return s == null ? defaultStr : s; } /** *

* Returns either the passed in String, or if the String is * empty or {@code null}, the value of {@code defaultStr}. *

* *
     * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
     * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
     * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
     * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
     * StringUtils.defaultIfEmpty("", null)      = null
     * 
*/ public static String defaultIfEmpty(final String s, final String defaultStr) { return isEmpty(s) ? defaultStr : s; } /** *

* Returns either the passed in String, or if the String is * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}. *

* *
     * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
     * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
     * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
     * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
     * StringUtils.defaultIfBlank("", null)      = null
     * 
*/ public static String defaultIfBlank(final String s, final String defaultStr) { return isBlank(s) ? defaultStr : s; } // Equals // ----------------------------------------------------------------------- /** *

* Compares two CharSequences, returning {@code true} if they represent * equal sequences of characters. *

* *

* {@code null}s are handled without exceptions. Two {@code null} references * are considered to be equal. The comparison is case sensitive. *

* *
     * StringUtils.equals(null, null)   = true
     * StringUtils.equals(null, "abc")  = false
     * StringUtils.equals("abc", null)  = false
     * StringUtils.equals("abc", "abc") = true
     * StringUtils.equals("abc", "ABC") = false
     * 
*/ public static boolean equals(final String s1, final String s2) { if (s1 == s2) { return true; } if (s1 == null || s2 == null) { return false; } return s1.equals(s2); } /** *

* Compares two CharSequences, returning {@code true} if they represent * equal sequences of characters, ignoring case. *

* *

* {@code null}s are handled without exceptions. Two {@code null} references * are considered equal. Comparison is case insensitive. *

* *
     * StringUtils.equalsIgnoreCase(null, null)   = true
     * StringUtils.equalsIgnoreCase(null, "abc")  = false
     * StringUtils.equalsIgnoreCase("abc", null)  = false
     * StringUtils.equalsIgnoreCase("abc", "abc") = true
     * StringUtils.equalsIgnoreCase("abc", "ABC") = true
     * 
*/ public static boolean equalsIgnoreCase(final String s1, final String s2) { if (s1 == null || s2 == null) { return s1 == s2; } else if (s1 == s2) { return true; } else if (s1.length() != s2.length()) { return false; } else { return s1.equals(s2); } } // startsWith // ----------------------------------------------------------------------- /** *

* Check if a String starts with a specified prefix. *

* *

* {@code null}s are handled without exceptions. Two {@code null} references * are considered to be equal. The comparison is case sensitive. *

* *
     * StringUtils.startsWith(null, null)      = true
     * StringUtils.startsWith(null, "abc")     = false
     * StringUtils.startsWith("abcdef", null)  = false
     * StringUtils.startsWith("abcdef", "abc") = true
     * StringUtils.startsWith("ABCDEF", "abc") = false
     * 
* * @see java.lang.String#startsWith(String) * @param s * the String to check, may be null * @param prefix * the prefix to find, may be null * @return {@code true} if the String starts with the prefix, case * sensitive, or both {@code null} */ public static boolean startsWith(final String s, final String prefix) { return startsWith(s, prefix, false); } /** *

* Case insensitive check if a String starts with a specified prefix. *

* *

* {@code null}s are handled without exceptions. Two {@code null} references * are considered to be equal. The comparison is case insensitive. *

* *
     * StringUtils.startsWithIgnoreCase(null, null)      = true
     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
     * 
* * @see java.lang.String#startsWith(String) */ public static boolean startsWithIgnoreCase(final String s, final String prefix) { return startsWith(s, prefix, true); } /** *

* Check if a String starts with a specified prefix (optionally case * insensitive). *

* * @see java.lang.String#startsWith(String) */ private static boolean startsWith(final String s, final String prefix, final boolean ignoreCase) { if (s == null || prefix == null) { return s == null && prefix == null; } if (prefix.length() > s.length()) { return false; } return s.toString().regionMatches(ignoreCase, 0, prefix.toString(), 0, prefix.length()); } public static int startsWithOne(String s, String... dest) { for (int i = 0; i < dest.length; i++) { String m = dest[i]; if (m != null) { if (s.startsWith(m)) return i; } } return -1; } public static int startsWithOneIgnoreCase(String s, String... dest) { for (int i = 0; i < dest.length; i++) { String m = dest[i]; if (m != null) { if (startsWithIgnoreCase(s, m)) return i; } } return -1; } public static boolean startsWithChar(final String s, final char c) { if (s == null || s.length() == 0) { return false; } return s.charAt(0) == c; } // endsWith // ----------------------------------------------------------------------- /** *

* Check if a String ends with a specified suffix. *

* *

* {@code null}s are handled without exceptions. Two {@code null} references * are considered to be equal. The comparison is case sensitive. *

* *
     * StringUtils.endsWith(null, null)      = true
     * StringUtils.endsWith(null, "def")     = false
     * StringUtils.endsWith("abcdef", null)  = false
     * StringUtils.endsWith("abcdef", "def") = true
     * StringUtils.endsWith("ABCDEF", "def") = false
     * StringUtils.endsWith("ABCDEF", "cde") = false
     * 
* * @see java.lang.String#endsWith(String) */ public static boolean endsWith(final String s, final String suffix) { return endsWith(s, suffix, false); } /** *

* Case insensitive check if a String ends with a specified suffix. *

* *

* {@code null}s are handled without exceptions. Two {@code null} references * are considered to be equal. The comparison is case insensitive. *

* *
     * StringUtils.endsWithIgnoreCase(null, null)      = true
     * StringUtils.endsWithIgnoreCase(null, "def")     = false
     * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
     * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
     * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
     * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
     * 
* * @see java.lang.String#endsWith(String) */ public static boolean endsWithIgnoreCase(final String s, final String suffix) { return endsWith(s, suffix, true); } /** *

* Check if a String ends with a specified suffix (optionally case * insensitive). *

* * @see java.lang.String#endsWith(String) */ private static boolean endsWith(final String s, final String suffix, final boolean ignoreCase) { if (s == null || suffix == null) { return s == null && suffix == null; } if (suffix.length() > s.length()) { return false; } final int strOffset = s.length() - suffix.length(); return s.toString().regionMatches(ignoreCase, strOffset, suffix.toString(), 0, suffix.length()); } public static int endsWithOne(String src, String... dest) { for (int i = 0; i < dest.length; i++) { String m = dest[i]; if (m != null) { if (src.endsWith(m)) return i; } } return -1; } public static int endsWithOneIgnoreCase(String s, String... dest) { for (int i = 0; i < dest.length; i++) { String m = dest[i]; if (m != null) { if (endsWithIgnoreCase(s, m)) return i; } } return -1; } public static boolean endsWithChar(final String s, final char c) { if (s == null || s.length() == 0) { return false; } return s.charAt(s.length() - 1) == c; } // ---------------------------------------------------------------- indexof and ignore cases /** * Finds first occurrence of a substring in the given source but within limited range [start, end). * It is fastest possible code, but still original String.indexOf(String, int) * is much faster (since it uses char[] value directly) and should be used when no range is needed. * * @param s source string for examination * @param substr substring to find * @param startIndex starting index * @param endIndex ending index * @return index of founded substring or -1 if substring not found */ public static int indexOf(String s, String substr, int startIndex, int endIndex) { if (startIndex < 0) { startIndex = 0; } int srclen = s.length(); if (endIndex > srclen) { endIndex = srclen; } int sublen = substr.length(); if (sublen == 0) { return startIndex > srclen ? srclen : startIndex; } int total = endIndex - sublen + 1; char c = substr.charAt(0); mainloop: for (int i = startIndex; i < total; i++) { if (s.charAt(i) != c) { continue; } int j = 1; int k = i + 1; while (j < sublen) { if (substr.charAt(j) != s.charAt(k)) { continue mainloop; } j++; k++; } return i; } return -1; } /** * Finds the first occurrence of a character in the given source but within limited range (start, end]. */ public static int indexOf(String s, char c, int startIndex, int endIndex) { if (startIndex < 0) { startIndex = 0; } int srclen = s.length(); if (endIndex > srclen) { endIndex = srclen; } for (int i = startIndex; i < endIndex; i++) { if (s.charAt(i) == c) { return i; } } return -1; } /** * Finds the first occurrence of a character in the given source but within limited range (start, end]. */ public static int indexOfIgnoreCase(String s, char c, int startIndex, int endIndex) { if (startIndex < 0) { startIndex = 0; } int srclen = s.length(); if (endIndex > srclen) { endIndex = srclen; } c = Character.toLowerCase(c); for (int i = startIndex; i < endIndex; i++) { if (Character.toLowerCase(s.charAt(i)) == c) { return i; } } return -1; } /** * Finds first index of a substring in the given source string with ignored case. * * @param s source string for examination * @param substr substring to find * * @return index of founded substring or -1 if substring is not found * @see #indexOfIgnoreCase(String, String, int) */ public static int indexOfIgnoreCase(String s, String substr) { return indexOfIgnoreCase(s, substr, 0, s.length()); } /** * Finds first index of a substring in the given source string with ignored * case. This seems to be the fastest way doing this, with common string * length and content (of course, with no use of Boyer-Mayer type of * algorithms). Other implementations are slower: getting char array first, * lower casing the source string, using String.regionMatch etc. * * @param s source string for examination * @param substr substring to find * @param startIndex starting index from where search begins * * @return index of founded substring or -1 if substring is not found */ public static int indexOfIgnoreCase(String s, String substr, int startIndex) { return indexOfIgnoreCase(s, substr, startIndex, s.length()); } /** * Finds first index of a substring in the given source string and range with * ignored case. * * @param s source string for examination * @param substr substring to find * @param startIndex starting index from where search begins * @param endIndex endint index * @return index of founded substring or -1 if substring is not found * @see #indexOfIgnoreCase(String, String, int) */ public static int indexOfIgnoreCase(String s, String substr, int startIndex, int endIndex) { if (startIndex < 0) { startIndex = 0; } int srclen = s.length(); if (endIndex > srclen) { endIndex = srclen; } int sublen = substr.length(); if (sublen == 0) { return startIndex > srclen ? srclen : startIndex; } substr = substr.toLowerCase(); int total = endIndex - sublen + 1; char c = substr.charAt(0); mainloop: for (int i = startIndex; i < total; i++) { if (Character.toLowerCase(s.charAt(i)) != c) { continue; } int j = 1; int k = i + 1; while (j < sublen) { char source = Character.toLowerCase(s.charAt(k)); if (substr.charAt(j) != source) { continue mainloop; } j++; k++; } return i; } return -1; } /** * Finds the very first index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null if * noting found. * * @param s source string * @param arr string array */ public static int[] indexOf(String s, String arr[]) { return indexOf(s, arr, 0); } /** * Finds the very first index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array * @param start starting position */ public static int[] indexOf(String s, String arr[], int start) { int arrLen = arr.length; int index = Integer.MAX_VALUE; int last = -1; for (int j = 0; j < arrLen; j++) { int i = s.indexOf(arr[j], start); if (i != -1) { if (i < index) { index = i; last = j; } } } return last == -1 ? null : new int[] { last, index }; } /** * Finds the very first index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null if * noting found. * * @param s source string * @param c char array */ public static int[] indexOf(String s, char c[]) { return indexOf(s, c, 0); } /** * Finds the very first index of a char from the specified array. It * returns an int[2] where int[0] represents the char index and int[1] * represents position where char was found. Returns null * if noting found. * * @param s source string * @param c char array * @param start starting position */ public static int[] indexOf(String s, char c[], int start) { int arrLen = c.length; int index = Integer.MAX_VALUE; int last = -1; for (int j = 0; j < arrLen; j++) { int i = s.indexOf(c[j], start); if (i != -1) { if (i < index) { index = i; last = j; } } } return last == -1 ? null : new int[] { last, index }; } /** * Finds the very first index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array */ public static int[] indexOfIgnoreCase(String s, String arr[]) { return indexOfIgnoreCase(s, arr, 0); } /** * Finds the very first index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array * @param start starting position */ public static int[] indexOfIgnoreCase(String s, String arr[], int start) { int arrLen = arr.length; int index = Integer.MAX_VALUE; int last = -1; for (int j = 0; j < arrLen; j++) { int i = indexOfIgnoreCase(s, arr[j], start); if (i != -1) { if (i < index) { index = i; last = j; } } } return last == -1 ? null : new int[] { last, index }; } /** * Finds last index of a substring in the given source string with ignored * case. * * @param s source string * @param substr substring to find * * @return last index of founded substring or -1 if substring is not found * @see #indexOfIgnoreCase(String, String, int) * @see #lastIndexOfIgnoreCase(String, String, int) */ public static int lastIndexOfIgnoreCase(String s, String substr) { return lastIndexOfIgnoreCase(s, substr, s.length(), 0); } /** * Finds last index of a substring in the given source string with ignored * case. * * @param s source string for examination * @param substr substring to find * @param startIndex starting index from where search begins * * @return last index of founded substring or -1 if substring is not found * @see #indexOfIgnoreCase(String, String, int) */ public static int lastIndexOfIgnoreCase(String s, String substr, int startIndex) { return lastIndexOfIgnoreCase(s, substr, startIndex, 0); } /** * Finds last index of a substring in the given source string with ignored * case in specified range. * * @param s source to examine * @param sub substring to find * @param startIndex starting index * @param endIndex end index * @return last index of founded substring or -1 if substring is not found */ public static int lastIndexOfIgnoreCase(String s, String sub, int startIndex, int endIndex) { int sublen = sub.length(); int srclen = s.length(); if (sublen == 0) { return startIndex > srclen ? srclen : (startIndex < -1 ? -1 : startIndex); } sub = sub.toLowerCase(); int total = srclen - sublen; if (total < 0) { return -1; } if (startIndex >= total) { startIndex = total; } if (endIndex < 0) { endIndex = 0; } char c = sub.charAt(0); mainloop: for (int i = startIndex; i >= endIndex; i--) { if (Character.toLowerCase(s.charAt(i)) != c) { continue; } int j = 1; int k = i + 1; while (j < sublen) { char source = Character.toLowerCase(s.charAt(k)); if (sub.charAt(j) != source) { continue mainloop; } j++; k++; } return i; } return -1; } /** * Finds last index of a substring in the given source string in specified range [end, start] * See {@link #indexOf(String, String, int, int)} for details about the speed. * * @param s source to examine * @param sub substring to find * @param startIndex starting index * @param endIndex end index * @return last index of founded substring or -1 if substring is not found */ public static int lastIndexOf(String s, String sub, int startIndex, int endIndex) { int sublen = sub.length(); int srclen = s.length(); if (sublen == 0) { return startIndex > srclen ? srclen : (startIndex < -1 ? -1 : startIndex); } int total = srclen - sublen; if (total < 0) { return -1; } if (startIndex >= total) { startIndex = total; } if (endIndex < 0) { endIndex = 0; } char c = sub.charAt(0); mainloop: for (int i = startIndex; i >= endIndex; i--) { if (s.charAt(i) != c) { continue; } int j = 1; int k = i + 1; while (j < sublen) { if (sub.charAt(j) != s.charAt(k)) { continue mainloop; } j++; k++; } return i; } return -1; } /** * Finds last index of a character in the given source string in specified range [end, start] */ public static int lastIndexOf(String s, char c, int startIndex, int endIndex) { int total = s.length() - 1; if (total < 0) { return -1; } if (startIndex >= total) { startIndex = total; } if (endIndex < 0) { endIndex = 0; } for (int i = startIndex; i >= endIndex; i--) { if (s.charAt(i) == c) { return i; } } return -1; } /** * Finds last index of a character in the given source string in specified range [end, start] */ public static int lastIndexOfIgnoreCase(String s, char c, int startIndex, int endIndex) { int total = s.length() - 1; if (total < 0) { return -1; } if (startIndex >= total) { startIndex = total; } if (endIndex < 0) { endIndex = 0; } c = Character.toLowerCase(c); for (int i = startIndex; i >= endIndex; i--) { if (Character.toLowerCase(s.charAt(i)) == c) { return i; } } return -1; } /** * Finds the very last index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array */ public static int[] lastIndexOf(String s, String arr[]) { return lastIndexOf(s, arr, s.length()); } /** * Finds the very last index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array * @param fromIndex starting position */ public static int[] lastIndexOf(String s, String arr[], int fromIndex) { int arrLen = arr.length; int index = -1; int last = -1; for (int j = 0; j < arrLen; j++) { int i = s.lastIndexOf(arr[j], fromIndex); if (i != -1) { if (i > index) { index = i; last = j; } } } return last == -1 ? null : new int[] { last, index }; } /** * Finds the very last index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param c char array */ public static int[] lastIndexOf(String s, char c[]) { return lastIndexOf(s, c, s.length()); } /** * Finds the very last index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param c char array * @param fromIndex starting position */ public static int[] lastIndexOf(String s, char c[], int fromIndex) { int arrLen = c.length; int index = -1; int last = -1; for (int j = 0; j < arrLen; j++) { int i = s.lastIndexOf(c[j], fromIndex); if (i != -1) { if (i > index) { index = i; last = j; } } } return last == -1 ? null : new int[] { last, index }; } /** * Finds the very last index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array * * @return int[2] */ public static int[] lastIndexOfIgnoreCase(String s, String arr[]) { return lastIndexOfIgnoreCase(s, arr, s.length()); } /** * Finds the very last index of a substring from the specified array. It * returns an int[2] where int[0] represents the substring index and int[1] * represents position where substring was found. Returns null * if noting found. * * @param s source string * @param arr string array * @param fromIndex starting position */ public static int[] lastIndexOfIgnoreCase(String s, String arr[], int fromIndex) { int arrLen = arr.length; int index = -1; int last = -1; for (int j = 0; j < arrLen; j++) { int i = lastIndexOfIgnoreCase(s, arr[j], fromIndex); if (i != -1) { if (i > index) { index = i; last = j; } } } return last == -1 ? null : new int[] { last, index }; } // Substring // ----------------------------------------------------------------------- /** *

* Gets a substring from the specified String avoiding exceptions. *

* *

* A negative start position can be used to start {@code n} characters from * the end of the String. *

* *

* A {@code null} String will return {@code null}. An empty ("") String will * return "". *

* *
     * StringUtils.substring(null, *)   = null
     * StringUtils.substring("", *)     = ""
     * StringUtils.substring("abc", 0)  = "abc"
     * StringUtils.substring("abc", 2)  = "c"
     * StringUtils.substring("abc", 4)  = ""
     * StringUtils.substring("abc", -2) = "bc"
     * StringUtils.substring("abc", -4) = "abc"
     * 
*/ public static String substring(final String s, int start) { if (s == null) { return null; } // handle negatives, which means last n characters if (start < 0) { start = s.length() + start; // remember start is negative } if (start < 0) { start = 0; } if (start > s.length()) { return ""; } return s.substring(start); } /** *

* Gets a substring from the specified String avoiding exceptions. *

* *

* A negative start position can be used to start/end {@code n} characters * from the end of the String. *

* *

* The returned substring starts with the character in the {@code start} * position and ends before the {@code end} position. All position counting * is zero-based -- i.e., to start at the beginning of the string use * {@code start = 0}. Negative start and end positions can be used to * specify offsets relative to the end of the String. *

* *

* If {@code start} is not strictly to the left of {@code end}, "" is * returned. *

* *
     * StringUtils.substring(null, *, *)    = null
     * StringUtils.substring("", * ,  *)    = "";
     * StringUtils.substring("abc", 0, 2)   = "ab"
     * StringUtils.substring("abc", 2, 0)   = ""
     * StringUtils.substring("abc", 2, 4)   = "c"
     * StringUtils.substring("abc", 4, 6)   = ""
     * StringUtils.substring("abc", 2, 2)   = ""
     * StringUtils.substring("abc", -2, -1) = "b"
     * StringUtils.substring("abc", -4, 2)  = "ab"
     * 
*/ public static String substring(final String s, int start, int end) { if (s == null) { return null; } // handle negatives if (end < 0) { end = s.length() + end; // remember end is negative } if (start < 0) { start = s.length() + start; // remember start is negative } // check length next if (end > s.length()) { end = s.length(); } // if start is greater than end, return "" if (start > end) { return ""; } if (start < 0) { start = 0; } if (end < 0) { end = 0; } return s.substring(start, end); } // SubStringAfter/SubStringBefore // ----------------------------------------------------------------------- /** *

* Gets the substring before the first occurrence of a separator. The * separator is not returned. *

* *

* A {@code null} string input will return {@code null}. An empty ("") * string input will return the empty string. A {@code null} separator will * return the input string. *

* *

* If nothing is found, the string input is returned. *

* *
     * StringUtils.substringBefore(null, *)      = null
     * StringUtils.substringBefore("", *)        = ""
     * StringUtils.substringBefore("abc", "a")   = ""
     * StringUtils.substringBefore("abcba", "b") = "a"
     * StringUtils.substringBefore("abc", "c")   = "ab"
     * StringUtils.substringBefore("abc", "d")   = "abc"
     * StringUtils.substringBefore("abc", "")    = ""
     * StringUtils.substringBefore("abc", null)  = "abc"
     * 
*/ public static String substringBefore(final String s, final String separator) { if (isEmpty(s) || separator == null) { return s; } if (separator.isEmpty()) { return ""; } final int pos = s.indexOf(separator); if (pos < 0) { return s; } return s.substring(0, pos); } /** *

* Gets the substring after the first occurrence of a separator. The * separator is not returned. *

* *

* A {@code null} string input will return {@code null}. An empty ("") * string input will return the empty string. A {@code null} separator will * return the empty string if the input string is not {@code null}. *

* *

* If nothing is found, the empty string is returned. *

* *
     * StringUtils.substringAfter(null, *)      = null
     * StringUtils.substringAfter("", *)        = ""
     * StringUtils.substringAfter(*, null)      = ""
     * StringUtils.substringAfter("abc", "a")   = "bc"
     * StringUtils.substringAfter("abcba", "b") = "cba"
     * StringUtils.substringAfter("abc", "c")   = ""
     * StringUtils.substringAfter("abc", "d")   = ""
     * StringUtils.substringAfter("abc", "")    = "abc"
     * 
*/ public static String substringAfter(final String s, final String separator) { if (isEmpty(s)) { return s; } if (separator == null) { return ""; } final int pos = s.indexOf(separator); if (pos < 0) { return ""; } return s.substring(pos + separator.length()); } /** *

* Gets the substring before the last occurrence of a separator. The * separator is not returned. *

* *

* A {@code null} string input will return {@code null}. An empty ("") * string input will return the empty string. An empty or {@code null} * separator will return the input string. *

* *

* If nothing is found, the string input is returned. *

* *
     * StringUtils.substringBeforeLast(null, *)      = null
     * StringUtils.substringBeforeLast("", *)        = ""
     * StringUtils.substringBeforeLast("abcba", "b") = "abc"
     * StringUtils.substringBeforeLast("abc", "c")   = "ab"
     * StringUtils.substringBeforeLast("a", "a")     = ""
     * StringUtils.substringBeforeLast("a", "z")     = "a"
     * StringUtils.substringBeforeLast("a", null)    = "a"
     * StringUtils.substringBeforeLast("a", "")      = "a"
     * 
*/ public static String substringBeforeLast(final String s, final String separator) { if (isEmpty(s) || isEmpty(separator)) { return s; } final int pos = s.lastIndexOf(separator); if (pos < 0) { return s; } return s.substring(0, pos); } /** *

* Gets the substring after the last occurrence of a separator. The * separator is not returned. *

* *

* A {@code null} string input will return {@code null}. An empty ("") * string input will return the empty string. An empty or {@code null} * separator will return the empty string if the input string is not * {@code null}. *

* *

* If nothing is found, the empty string is returned. *

* *
     * StringUtils.substringAfterLast(null, *)      = null
     * StringUtils.substringAfterLast("", *)        = ""
     * StringUtils.substringAfterLast(*, "")        = ""
     * StringUtils.substringAfterLast(*, null)      = ""
     * StringUtils.substringAfterLast("abc", "a")   = "bc"
     * StringUtils.substringAfterLast("abcba", "b") = "a"
     * StringUtils.substringAfterLast("abc", "c")   = ""
     * StringUtils.substringAfterLast("a", "a")     = ""
     * StringUtils.substringAfterLast("a", "z")     = ""
     * 
*/ public static String substringAfterLast(final String s, final String separator) { if (isEmpty(s)) { return s; } if (isEmpty(separator)) { return ""; } final int pos = s.lastIndexOf(separator); if (pos < 0 || pos == s.length() - separator.length()) { return ""; } return s.substring(pos + separator.length()); } // Substring between // ----------------------------------------------------------------------- /** *

* Gets the String that is nested in between two instances of the same * String. *

* *

* A {@code null} input String returns {@code null}. A {@code null} tag * returns {@code null}. *

* *
     * StringUtils.substringBetween(null, *)            = null
     * StringUtils.substringBetween("", "")             = ""
     * StringUtils.substringBetween("", "tag")          = null
     * StringUtils.substringBetween("tagabctag", null)  = null
     * StringUtils.substringBetween("tagabctag", "")    = ""
     * StringUtils.substringBetween("tagabctag", "tag") = "abc"
     * 
*/ public static String substringBetween(final String s, final String tag) { return substringBetween(s, tag, tag); } /** *

* Gets the String that is nested in between two Strings. Only the first * match is returned. *

* *

* A {@code null} input String returns {@code null}. A {@code null} * open/close returns {@code null} (no match). An empty ("") open and close * returns an empty string. *

* *
     * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
     * StringUtils.substringBetween(null, *, *)          = null
     * StringUtils.substringBetween(*, null, *)          = null
     * StringUtils.substringBetween(*, *, null)          = null
     * StringUtils.substringBetween("", "", "")          = ""
     * StringUtils.substringBetween("", "", "]")         = null
     * StringUtils.substringBetween("", "[", "]")        = null
     * StringUtils.substringBetween("yabcz", "", "")     = ""
     * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
     * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
     * 
*/ public static String substringBetween(final String s, final String open, final String close) { if (s == null || open == null || close == null) { return null; } final int start = s.indexOf(open); if (start >= 0) { final int end = s.indexOf(close, start + open.length()); if (end >= 0) { return s.substring(start + open.length(), end); } } return null; } // Left/Right/Mid // ----------------------------------------------------------------------- /** *

* Gets the leftmost {@code len} characters of a String. *

* *

* If {@code len} characters are not available, or the String is * {@code null}, the String will be returned without an exception. An empty * String is returned if len is negative. *

* *
     * StringUtils.left(null, *)    = null
     * StringUtils.left(*, -ve)     = ""
     * StringUtils.left("", *)      = ""
     * StringUtils.left("abc", 0)   = ""
     * StringUtils.left("abc", 2)   = "ab"
     * StringUtils.left("abc", 4)   = "abc"
     * 
*/ public static String left(final String s, final int len) { if (s == null) { return null; } if (len < 0) { return ""; } if (s.length() <= len) { return s; } return s.substring(0, len); } /** *

* Gets the rightmost {@code len} characters of a String. *

* *

* If {@code len} characters are not available, or the String is * {@code null}, the String will be returned without an an exception. An * empty String is returned if len is negative. *

* *
     * StringUtils.right(null, *)    = null
     * StringUtils.right(*, -ve)     = ""
     * StringUtils.right("", *)      = ""
     * StringUtils.right("abc", 0)   = ""
     * StringUtils.right("abc", 2)   = "bc"
     * StringUtils.right("abc", 4)   = "abc"
     * 
*/ public static String right(final String s, final int len) { if (s == null) { return null; } if (len < 0) { return ""; } if (s.length() <= len) { return s; } return s.substring(s.length() - len); } /** *

* Gets {@code len} characters from the middle of a String. *

* *

* If {@code len} characters are not available, the remainder of the String * will be returned without an exception. If the String is {@code null}, * {@code null} will be returned. An empty String is returned if len is * negative or exceeds the length of {@code str}. *

* *
     * StringUtils.mid(null, *, *)    = null
     * StringUtils.mid(*, *, -ve)     = ""
     * StringUtils.mid("", 0, *)      = ""
     * StringUtils.mid("abc", 0, 2)   = "ab"
     * StringUtils.mid("abc", 0, 4)   = "abc"
     * StringUtils.mid("abc", 2, 4)   = "c"
     * StringUtils.mid("abc", 4, 2)   = ""
     * StringUtils.mid("abc", -2, 2)  = "ab"
     * 
*/ public static String mid(final String s, int pos, final int len) { if (s == null) { return null; } if (len < 0 || pos > s.length()) { return ""; } if (pos < 0) { pos = 0; } if (s.length() <= pos + len) { return s.substring(pos); } return s.substring(pos, pos + len); } // Padding // ----------------------------------------------------------------------- /** *

* Repeat a String {@code repeat} times to form a new String. *

* *
     * StringUtils.repeat(null, 2) = null
     * StringUtils.repeat("", 0)   = ""
     * StringUtils.repeat("", 2)   = ""
     * StringUtils.repeat("a", 3)  = "aaa"
     * StringUtils.repeat("ab", 2) = "abab"
     * StringUtils.repeat("a", -2) = ""
     * 
*/ public static String repeat(final String s, final int repeat) { if (s == null) { return null; } if (repeat <= 0) { return ""; } final int inputLength = s.length(); if (repeat == 1 || inputLength == 0) { return s; } final int outputLength = inputLength * repeat; switch (inputLength) { case 1: return repeat(s.charAt(0), repeat); case 2: final char ch0 = s.charAt(0); final char ch1 = s.charAt(1); final char[] output2 = new char[outputLength]; for (int i = repeat * 2 - 2; i >= 0; i--, i--) { output2[i] = ch0; output2[i + 1] = ch1; } return new String(output2); default: final StringBuilder buf = new StringBuilder(outputLength); for (int i = 0; i < repeat; i++) { buf.append(s); } return buf.toString(); } } /** *

* Repeat a String {@code repeat} times to form a new String, with a String * separator injected each time. *

* *
     * StringUtils.repeat(null, null, 2) = null
     * StringUtils.repeat(null, "x", 2)  = null
     * StringUtils.repeat("", null, 0)   = ""
     * StringUtils.repeat("", "", 2)     = ""
     * StringUtils.repeat("", "x", 3)    = "xxx"
     * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
     * 
*/ public static String repeat(final String s, final String separator, final int repeat) { if (s == null || separator == null) { return repeat(s, repeat); } // given that repeat(String, int) is quite optimized, better to rely on // it than try and splice this into it final String result = repeat(s + separator, repeat); return removeEnd(result, separator); } /** *

* Returns padding using the specified delimiter repeated to a given length. *

* *
     * StringUtils.repeat('e', 0)  = ""
     * StringUtils.repeat('e', 3)  = "eee"
     * StringUtils.repeat('e', -2) = ""
     * 
* *

* Note: this method doesn't not support padding with Unicode * Supplementary Characters as they require a pair of {@code char}s to * be represented. If you are needing to support full I18N of your * applications consider using {@link #repeat(String, int)} instead. *

* @see #repeat(String, int) */ public static String repeat(final char ch, final int repeat) { final char[] buf = new char[repeat]; for (int i = repeat - 1; i >= 0; i--) { buf[i] = ch; } return new String(buf); } public static String leftPad(String str, int size) { return leftPad(str, size, ' '); } public static String leftPad(String str, int size, char padChar) { if (str == null) { return null; } int pads = size - str.length(); if (pads <= 0) { return str; } if (pads > 8192) { return leftPad(str, size, String.valueOf(padChar)); } return repeat(padChar, pads).concat(str); } public static String leftPad(String str, int size, String padStr) { if (str == null) { return null; } if (isEmpty(padStr)) { padStr = " "; } int padLen = padStr.length(); int strLen = str.length(); int pads = size - strLen; if (pads <= 0) { return str; } if ((padLen == 1) && (pads <= 8192)) { return leftPad(str, size, padStr.charAt(0)); } if (pads == padLen) { return padStr.concat(str); } if (pads < padLen) { return padStr.substring(0, pads).concat(str); } char[] padding = new char[pads]; char[] padChars = padStr.toCharArray(); for (int i = 0; i < pads; i++) { padding[i] = padChars[(i % padLen)]; } return new String(padding).concat(str); } public static String rightPad(String str, int size) { return rightPad(str, size, ' '); } public static String rightPad(String str, int size, char padChar) { if (str == null) { return null; } int pads = size - str.length(); if (pads <= 0) { return str; } if (pads > 8192) { return rightPad(str, size, String.valueOf(padChar)); } return str.concat(repeat(padChar, pads)); } public static String rightPad(String str, int size, String padStr) { if (str == null) { return null; } if (isEmpty(padStr)) { padStr = " "; } int padLen = padStr.length(); int strLen = str.length(); int pads = size - strLen; if (pads <= 0) { return str; } if ((padLen == 1) && (pads <= 8192)) { return rightPad(str, size, padStr.charAt(0)); } if (pads == padLen) { return str.concat(padStr); } if (pads < padLen) { return str.concat(padStr.substring(0, pads)); } char[] padding = new char[pads]; char[] padChars = padStr.toCharArray(); for (int i = 0; i < pads; i++) { padding[i] = padChars[(i % padLen)]; } return str.concat(new String(padding)); } public static String center(String str, int size) { return center(str, size, ' '); } public static String center(String str, int size, char padChar) { if ((str == null) || (size <= 0)) { return str; } int strLen = str.length(); int pads = size - strLen; if (pads <= 0) { return str; } str = leftPad(str, strLen + pads / 2, padChar); str = rightPad(str, size, padChar); return str; } public static String reverse(String s) { StringBuilder result = new StringBuilder(s.length()); for (int i = s.length() - 1; i >= 0; i--) { result.append(s.charAt(i)); } return result.toString(); } // Delete // ----------------------------------------------------------------------- /** *

* Deletes all whitespaces from a String as defined by * {@link Character#isWhitespace(char)}. *

* *
     * StringUtils.deleteWhitespace(null)         = null
     * StringUtils.deleteWhitespace("")           = ""
     * StringUtils.deleteWhitespace("abc")        = "abc"
     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
     * 
* * @param s * the String to delete whitespace from, may be null * @return the String without whitespaces, {@code null} if null String input */ public static String deleteWhitespace(final String s) { if (isEmpty(s)) { return s; } final int sz = s.length(); final char[] chs = new char[sz]; int count = 0; for (int i = 0; i < sz; i++) { if (!Character.isWhitespace(s.charAt(i))) { chs[count++] = s.charAt(i); } } if (count == sz) { return s; } return new String(chs, 0, count); } // Remove // ----------------------------------------------------------------------- /** *

* Removes a substring only if it is at the beginning of a source string, * otherwise returns the source string. *

* *

* A {@code null} source string will return {@code null}. An empty ("") * source string will return the empty string. A {@code null} search string * will return the source string. *

* *
     * StringUtils.removeStart(null, *)      = null
     * StringUtils.removeStart("", *)        = ""
     * StringUtils.removeStart(*, null)      = *
     * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
     * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
     * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
     * StringUtils.removeStart("abc", "")    = "abc"
     * 
*/ public static String removeStart(final String s, final String remove) { if (isEmpty(s) || isEmpty(remove)) { return s; } if (s.startsWith(remove)) { return s.substring(remove.length()); } return s; } /** *

* Case insensitive removal of a substring if it is at the beginning of a * source string, otherwise returns the source string. *

* *

* A {@code null} source string will return {@code null}. An empty ("") * source string will return the empty string. A {@code null} search string * will return the source string. *

* *
     * StringUtils.removeStartIgnoreCase(null, *)      = null
     * StringUtils.removeStartIgnoreCase("", *)        = ""
     * StringUtils.removeStartIgnoreCase(*, null)      = *
     * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
     * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
     * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
     * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
     * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
     * 
*/ public static String removeStartIgnoreCase(final String s, final String remove) { if (isEmpty(s) || isEmpty(remove)) { return s; } if (startsWithIgnoreCase(s, remove)) { return s.substring(remove.length()); } return s; } /** *

* Removes a substring only if it is at the end of a source string, * otherwise returns the source string. *

* *

* A {@code null} source string will return {@code null}. An empty ("") * source string will return the empty string. A {@code null} search string * will return the source string. *

* *
     * StringUtils.removeEnd(null, *)      = null
     * StringUtils.removeEnd("", *)        = ""
     * StringUtils.removeEnd(*, null)      = *
     * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
     * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
     * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
     * StringUtils.removeEnd("abc", "")    = "abc"
     * 
*/ public static String removeEnd(final String s, final String remove) { if (isEmpty(s) || isEmpty(remove)) { return s; } if (s.endsWith(remove)) { return s.substring(0, s.length() - remove.length()); } return s; } /** *

* Case insensitive removal of a substring if it is at the end of a source * string, otherwise returns the source string. *

* *

* A {@code null} source string will return {@code null}. An empty ("") * source string will return the empty string. A {@code null} search string * will return the source string. *

* *
     * StringUtils.removeEndIgnoreCase(null, *)      = null
     * StringUtils.removeEndIgnoreCase("", *)        = ""
     * StringUtils.removeEndIgnoreCase(*, null)      = *
     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
     * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
     * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
     * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
     * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
     * 
*/ public static String removeEndIgnoreCase(final String s, final String remove) { if (isEmpty(s) || isEmpty(remove)) { return s; } if (endsWithIgnoreCase(s, remove)) { return s.substring(0, s.length() - remove.length()); } return s; } /** *

* Removes all occurrences of a substring from within the source string. *

* *

* A {@code null} source string will return {@code null}. An empty ("") * source string will return the empty string. A {@code null} remove string * will return the source string. An empty ("") remove string will return * the source string. *

* *
     * StringUtils.remove(null, *)        = null
     * StringUtils.remove("", *)          = ""
     * StringUtils.remove(*, null)        = *
     * StringUtils.remove(*, "")          = *
     * StringUtils.remove("queued", "ue") = "qd"
     * StringUtils.remove("queued", "zz") = "queued"
     * 
*/ public static String remove(final String s, final String remove) { if (isEmpty(s) || isEmpty(remove)) { return s; } return replace(s, remove, "", -1); } /** *

* Removes all occurrences of a character from within the source string. *

* *

* A {@code null} source string will return {@code null}. An empty ("") * source string will return the empty string. *

* *
     * StringUtils.remove(null, *)       = null
     * StringUtils.remove("", *)         = ""
     * StringUtils.remove("queued", 'u') = "qeed"
     * StringUtils.remove("queued", 'z') = "queued"
     * 
*/ public static String remove(final String s, final char remove) { if (isEmpty(s) || s.indexOf(remove) < 0) { return s; } final char[] chars = s.toCharArray(); int pos = 0; for (int i = 0; i < chars.length; i++) { if (chars[i] != remove) { chars[pos++] = chars[i]; } } return new String(chars, 0, pos); } /** * Removes all characters contained in provided string. * * @param s source string * @param chars string containing characters to remove */ public static String removeChars(String s, String chars) { int i = s.length(); StringBuilder sb = new StringBuilder(i); for (int j = 0; j < i; j++) { char c = s.charAt(j); if (chars.indexOf(c) == -1) { sb.append(c); } } return sb.toString(); } /** * Removes set of characters from string. * * @param s string * @param chars characters to remove */ public static String removeChars(String s, char... chars) { int i = s.length(); StringBuilder sb = new StringBuilder(i); mainloop: for (int j = 0; j < i; j++) { char c = s.charAt(j); for (char aChar : chars) { if (c == aChar) { continue mainloop; } } sb.append(c); } return sb.toString(); } public static String prefix(String s, String prefix) { if (!s.startsWith(prefix)) { s = prefix + s; } return s; } public static String suffix(String s, String suffix) { if (!s.endsWith(suffix)) { s = s + suffix; } return s; } // Replacing // ----------------------------------------------------------------------- /** *

* Replaces a String with another String inside a larger String, once. *

* *

* A {@code null} reference passed to this method is a no-op. *

* *
     * StringUtils.replaceOnce(null, *, *)        = null
     * StringUtils.replaceOnce("", *, *)          = ""
     * StringUtils.replaceOnce("any", null, *)    = "any"
     * StringUtils.replaceOnce("any", *, null)    = "any"
     * StringUtils.replaceOnce("any", "", *)      = "any"
     * StringUtils.replaceOnce("aba", "a", null)  = "aba"
     * StringUtils.replaceOnce("aba", "a", "")    = "ba"
     * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
     * 
* * @see #replace(String text, String searchString, String replacement, int * max) */ public static String replaceOnce(final String text, final String searchString, final String replacement) { return replace(text, searchString, replacement, 1); } /** * Replaces each substring of the source String that matches the given * regular expression with the given replacement using the * {@link Pattern#DOTALL} option. DOTALL is also know as single-line mode in * Perl. This call is also equivalent to: *
    *
  • {@code source.replaceAll("(?s)" + regex, replacement)}
  • *
  • * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)} *
  • *
* * @see String#replaceAll(String, String) * @see Pattern#DOTALL */ public static String replacePattern(final String source, final String regex, final String replacement) { return Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement); } /** *

* Replaces all occurrences of a String within another String. *

* *

* A {@code null} reference passed to this method is a no-op. *

* *
     * StringUtils.replace(null, *, *)        = null
     * StringUtils.replace("", *, *)          = ""
     * StringUtils.replace("any", null, *)    = "any"
     * StringUtils.replace("any", *, null)    = "any"
     * StringUtils.replace("any", "", *)      = "any"
     * StringUtils.replace("aba", "a", null)  = "aba"
     * StringUtils.replace("aba", "a", "")    = "b"
     * StringUtils.replace("aba", "a", "z")   = "zbz"
     * 
*/ public static String replace(final String text, final String searchString, final String replacement) { return replace(text, searchString, replacement, -1); } /** *

* Replaces a String with another String inside a larger String, for the * first {@code max} values of the search String. *

* *

* A {@code null} reference passed to this method is a no-op. *

* *
     * StringUtils.replace(null, *, *, *)         = null
     * StringUtils.replace("", *, *, *)           = ""
     * StringUtils.replace("any", null, *, *)     = "any"
     * StringUtils.replace("any", *, null, *)     = "any"
     * StringUtils.replace("any", "", *, *)       = "any"
     * StringUtils.replace("any", *, *, 0)        = "any"
     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
     * StringUtils.replace("abaa", "a", "", -1)   = "b"
     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
     * 
*/ public static String replace(final String text, final String searchString, final String replacement, int max) { if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { return text; } int start = 0; int end = text.indexOf(searchString, start); if (end < 0) { return text; } final int replLength = searchString.length(); int increase = replacement.length() - replLength; increase = increase < 0 ? 0 : increase; increase *= max < 0 ? 16 : max > 64 ? 64 : max; final StringBuilder buf = new StringBuilder(text.length() + increase); while (end >= 0) { buf.append(text.substring(start, end)).append(replacement); start = end + replLength; if (--max == 0) { break; } end = text.indexOf(searchString, start); } buf.append(text.substring(start)); return buf.toString(); } /** *

* Replaces all occurrences of Strings within another String. *

* *

* A {@code null} reference passed to this method is a no-op, or if any * "search string" or "string to replace" is null, that replace will be * ignored. This will not repeat. For repeating replaces, call the * overloaded method. *

* *
     *  StringUtils.replaceEach(null, *, *)        = null
     *  StringUtils.replaceEach("", *, *)          = ""
     *  StringUtils.replaceEach("aba", null, null) = "aba"
     *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
     *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
     *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
     *  (example of how it does not repeat)
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
     * 
*/ public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { return replaceEach(text, searchList, replacementList, false, 0); } /** *

* Replaces all occurrences of Strings within another String. *

* *

* A {@code null} reference passed to this method is a no-op, or if any * "search string" or "string to replace" is null, that replace will be * ignored. *

* *
     *  StringUtils.replaceEach(null, *, *, *) = null
     *  StringUtils.replaceEach("", *, *, *) = ""
     *  StringUtils.replaceEach("aba", null, null, *) = "aba"
     *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
     *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
     *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
     *  (example of how it repeats)
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, true) = IllegalStateException
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, false) = "dcabe"
     * 
*/ public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { // timeToLive should be 0 if not used or nothing to replace, else it's // the length of the replace array final int timeToLive = searchList == null ? 0 : searchList.length; return replaceEach(text, searchList, replacementList, true, timeToLive); } /** *

* Replaces all occurrences of Strings within another String. *

* *

* A {@code null} reference passed to this method is a no-op, or if any * "search string" or "string to replace" is null, that replace will be * ignored. *

* *
     *  StringUtils.replaceEach(null, *, *, *) = null
     *  StringUtils.replaceEach("", *, *, *) = ""
     *  StringUtils.replaceEach("aba", null, null, *) = "aba"
     *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
     *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
     *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
     *  (example of how it repeats)
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *) = IllegalStateException
     * 
*/ private static String replaceEach(final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { if (text == null || text.isEmpty() || searchList == null || searchList.length == 0 || replacementList == null || replacementList.length == 0) { return text; } // if recursing, this shouldn't be less than 0 if (timeToLive < 0) { throw new IllegalStateException("Aborting to protect against StackOverflowError - " + "output of one loop is the input of another"); } final int searchLength = searchList.length; final int replacementLength = replacementList.length; // make sure lengths are ok, these need to be equal if (searchLength != replacementLength) { throw new IllegalArgumentException("Search and Replace array lengths don't match: " + searchLength + " vs " + replacementLength); } // keep track of which still have matches final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; // index on index that the match was found int textIndex = -1; int replaceIndex = -1; int tempIndex = -1; // index of replace array that will replace the search string found // NOTE: logic duplicated below START for (int i = 0; i < searchLength; i++) { if (noMoreMatchesForReplIndex[i] || searchList[i] == null || searchList[i].isEmpty() || replacementList[i] == null) { continue; } tempIndex = text.indexOf(searchList[i]); // see if we need to keep searching for this if (tempIndex == -1) { noMoreMatchesForReplIndex[i] = true; } else { if (textIndex == -1 || tempIndex < textIndex) { textIndex = tempIndex; replaceIndex = i; } } } // NOTE: logic mostly below END // no search strings found, we are done if (textIndex == -1) { return text; } int start = 0; // get a good guess on the size of the result buffer so it doesn't have // to double if it goes over a bit int increase = 0; // count the replacement text elements that are larger than their // corresponding text being replaced for (int i = 0; i < searchList.length; i++) { if (searchList[i] == null || replacementList[i] == null) { continue; } final int greater = replacementList[i].length() - searchList[i].length(); if (greater > 0) { increase += 3 * greater; // assume 3 matches } } // have upper-bound at 20% increase, then let Java take over increase = Math.min(increase, text.length() / 5); final StringBuilder buf = new StringBuilder(text.length() + increase); while (textIndex != -1) { for (int i = start; i < textIndex; i++) { buf.append(text.charAt(i)); } buf.append(replacementList[replaceIndex]); start = textIndex + searchList[replaceIndex].length(); textIndex = -1; replaceIndex = -1; tempIndex = -1; // find the next earliest match // NOTE: logic mostly duplicated above START for (int i = 0; i < searchLength; i++) { if (noMoreMatchesForReplIndex[i] || searchList[i] == null || searchList[i].isEmpty() || replacementList[i] == null) { continue; } tempIndex = text.indexOf(searchList[i], start); // see if we need to keep searching for this if (tempIndex == -1) { noMoreMatchesForReplIndex[i] = true; } else { if (textIndex == -1 || tempIndex < textIndex) { textIndex = tempIndex; replaceIndex = i; } } } // NOTE: logic duplicated above END } final int textLength = text.length(); for (int i = start; i < textLength; i++) { buf.append(text.charAt(i)); } final String result = buf.toString(); if (!repeat) { return result; } return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); } // Replace, character based // ----------------------------------------------------------------------- /** *

* Replaces all occurrences of a character in a String with another. This is * a null-safe version of {@link String#replace(char, char)}. *

* *

* A {@code null} string input returns {@code null}. An empty ("") string * input returns an empty string. *

* *
     * StringUtils.replaceChars(null, *, *)        = null
     * StringUtils.replaceChars("", *, *)          = ""
     * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
     * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
     * 
*/ public static String replaceChars(final String str, final char searchChar, final char replaceChar) { if (str == null) { return null; } return str.replace(searchChar, replaceChar); } /** *

* Replaces multiple characters in a String in one go. This method can also * be used to delete characters. *

* *

* For example:
* replaceChars("hello", "ho", "jy") = jelly * . *

* *

* A {@code null} string input returns {@code null}. An empty ("") string * input returns an empty string. A null or empty set of search characters * returns the input string. *

* *

* The length of the search characters should normally equal the length of * the replace characters. If the search characters is longer, then the * extra search characters are deleted. If the search characters is shorter, * then the extra replace characters are ignored. *

* *
     * StringUtils.replaceChars(null, *, *)           = null
     * StringUtils.replaceChars("", *, *)             = ""
     * StringUtils.replaceChars("abc", null, *)       = "abc"
     * StringUtils.replaceChars("abc", "", *)         = "abc"
     * StringUtils.replaceChars("abc", "b", null)     = "ac"
     * StringUtils.replaceChars("abc", "b", "")       = "ac"
     * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
     * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
     * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
     * 
*/ public static String replaceChars(final String str, final String searchChars, String replaceChars) { if (isEmpty(str) || isEmpty(searchChars)) { return str; } if (replaceChars == null) { replaceChars = ""; } boolean modified = false; final int replaceCharsLength = replaceChars.length(); final int strLength = str.length(); final StringBuilder buf = new StringBuilder(strLength); for (int i = 0; i < strLength; i++) { final char ch = str.charAt(i); final int index = searchChars.indexOf(ch); if (index >= 0) { modified = true; if (index < replaceCharsLength) { buf.append(replaceChars.charAt(index)); } } else { buf.append(ch); } } if (modified) { return buf.toString(); } return str; } public static String[] split(String str, String delimiter) { if (str == null) return null; List results = new ArrayList(); int ipos = 0, lastpos = 0; while ((ipos = str.indexOf(delimiter, lastpos)) != -1) { results.add(str.substring(lastpos, ipos)); lastpos = ipos + delimiter.length(); } results.add(str.substring(lastpos)); return results.toArray(new String[results.size()]); } public static String[] split(String str, char delimiter) { if (str == null) return null; List results = new ArrayList(); int ipos = 0, lastpos = 0; while ((ipos = str.indexOf(delimiter, lastpos)) != -1) { results.add(str.substring(lastpos, ipos)); lastpos = ipos + 1; } results.add(str.substring(lastpos)); return results.toArray(new String[results.size()]); } public static String[] splitChars(String str, String delimiters) { if (str == null) return null; List results = new ArrayList(); int lastpos = 0; for (int i = 0, len = str.length(); i < len; i++) { char c = str.charAt(i); if (delimiters.indexOf(c) != -1) { results.add(str.substring(lastpos, i)); lastpos = i + 1; } } results.add(str.substring(lastpos)); return results.toArray(new String[results.size()]); } public static String[] splitChars(String str, char... delimiters) { if (str == null) return null; List results = new ArrayList(); int lastpos = 0; for (int i = 0, len = str.length(); i < len; i++) { char c = str.charAt(i); if (ArrayUtils.contains(delimiters, c)) { results.add(str.substring(lastpos, i)); lastpos = i + 1; } } results.add(str.substring(lastpos)); return results.toArray(new String[results.size()]); } /** * 按逗号分隔,两边加引号的不分割(CSV 规则). */ public static String[] splitCSV(String str) { if (str == null) return null; String[] parts = StringUtils.split(str, ','); List results = new ArrayList(); for (int i = 0; i < parts.length; i++) { String s = parts[i].trim(); if (s.length() == 0) { results.add(s); } else { char c = s.charAt(0); if (c == '"' || c == '\'' || c == '`') { StringBuilder sb = new StringBuilder(); sb.append(s); while (i + 1 < parts.length) { if (sb.length() > 1 && s.length() > 0 && s.charAt(s.length() - 1) == c) { break; } s = parts[++i]; sb.append(',').append(s); } s = sb.toString().trim(); if (s.charAt(s.length() - 1) == c) { s = s.substring(1, s.length() - 1); } results.add(s); } else { results.add(s); } } } return results.toArray(new String[results.size()]); } public static String join(String... parts) { StringBuilder sb = new StringBuilder(parts.length); for (String part : parts) { sb.append(part); } return sb.toString(); } public static String join(Iterable elements, String separator) { if (elements == null) { return ""; } return join(elements.iterator(), separator); } public static String join(Iterator elements, String separator) { if (elements == null) { return ""; } StringBuilder sb = new StringBuilder(); while (elements.hasNext()) { Object o = elements.next(); if (sb.length() > 0 && separator != null) { sb.append(separator); } sb.append(o); } return sb.toString(); } public static String join(Object[] elements, String separator) { if (elements == null) { return ""; } StringBuilder sb = new StringBuilder(); for (Object o : elements) { if (sb.length() > 0 && separator != null) { sb.append(separator); } sb.append(o); } return sb.toString(); } public static int count(String source, String substr) { return count(source, substr, 0); } public static int count(String source, String substr, int start) { if (source == null || source.length() == 0) { return 0; } int count = 0; int j = start; int sublen = substr.length(); if (sublen == 0) return 0; while (true) { int i = source.indexOf(substr, j); if (i == -1) { break; } count++; j = i + sublen; } return count; } public static int count(String source, char c) { return count(source, c, 0); } public static int count(String source, char c, int start) { if (source == null || source.length() == 0) { return 0; } int count = 0; int j = start; while (true) { int i = source.indexOf(c, j); if (i == -1) { break; } count++; j = i + 1; } return count; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy