You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
555 lines
18 KiB
555 lines
18 KiB
package helper; |
|
|
|
import java.io.UnsupportedEncodingException; |
|
import java.util.Arrays; |
|
import java.util.StringTokenizer; |
|
|
|
/** |
|
* <p>Operations on {@link java.lang.String} that are |
|
* <code>null</code> safe.</p> |
|
* <p/> |
|
* <ul> |
|
* <li><b>IsEmpty/IsBlank</b> |
|
* - checks if a String contains text</li> |
|
* <li><b>Trim/Strip</b> |
|
* - removes leading and trailing whitespace</li> |
|
* <li><b>Equals</b> |
|
* - compares two strings null-safe</li> |
|
* <li><b>startsWith</b> |
|
* - check if a String starts with a prefix null-safe</li> |
|
* <li><b>endsWith</b> |
|
* - check if a String ends with a suffix null-safe</li> |
|
* <li><b>IndexOf/LastIndexOf/Contains</b> |
|
* - null-safe index-of checks |
|
* <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b> |
|
* - index-of any of a set of Strings</li> |
|
* <li><b>ContainsOnly/ContainsNone/ContainsAny</b> |
|
* - does String contains only/none/any of these characters</li> |
|
* <li><b>Substring/Left/Right/Mid</b> |
|
* - null-safe substring extractions</li> |
|
* <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b> |
|
* - substring extraction relative to other strings</li> |
|
* <li><b>Split/Join</b> |
|
* - splits a String into an array of substrings and vice versa</li> |
|
* <li><b>Remove/Delete</b> |
|
* - removes part of a String</li> |
|
* <li><b>Replace/Overlay</b> |
|
* - Searches a String and replaces one String with another</li> |
|
* <li><b>Chomp/Chop</b> |
|
* - removes the last part of a String</li> |
|
* <li><b>LeftPad/RightPad/Center/Repeat</b> |
|
* - pads a String</li> |
|
* <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b> |
|
* - changes the case of a String</li> |
|
* <li><b>CountMatches</b> |
|
* - counts the number of occurrences of one String in another</li> |
|
* <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b> |
|
* - checks the characters in a String</li> |
|
* <li><b>DefaultString</b> |
|
* - protects against a null input String</li> |
|
* <li><b>Reverse/ReverseDelimited</b> |
|
* - reverses a String</li> |
|
* <li><b>Abbreviate</b> |
|
* - abbreviates a string using ellipsis</li> |
|
* <li><b>Difference</b> |
|
* - compares Strings and reports on their differences</li> |
|
* <li><b>LevensteinDistance</b> |
|
* - the number of changes needed to change one String into another</li> |
|
* </ul> |
|
* <p/> |
|
* <p>The <code>helper.StringUtils</code> class defines certain words related to |
|
* String handling.</p> |
|
* <p/> |
|
* <ul> |
|
* <li>null - <code>null</code></li> |
|
* <li>empty - a zero-length string (<code>""</code>)</li> |
|
* <li>space - the space character (<code>' '</code>, char 32)</li> |
|
* <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> |
|
* <li>trim - the characters <= 32 as in {@link String#trim()}</li> |
|
* </ul> |
|
* <p/> |
|
* <p><code>helper.StringUtils</code> handles <code>null</code> input Strings quietly. |
|
* That is to say that a <code>null</code> input will return <code>null</code>. |
|
* Where a <code>boolean</code> or <code>int</code> is being returned |
|
* details vary by method.</p> |
|
* <p/> |
|
* <p>A side effect of the <code>null</code> handling is that a |
|
* <code>NullPointerException</code> should be considered a bug in |
|
* <code>helper.StringUtils</code> (except for deprecated methods).</p> |
|
* <p/> |
|
* <p>Methods in this class give sample code to explain their operation. |
|
* The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p> |
|
* |
|
* @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a> |
|
* @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> |
|
* @author Daniel L. Rall |
|
* @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a> |
|
* @author <a href="mailto:ed@apache.org">Ed Korthof</a> |
|
* @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a> |
|
* @author Stephen Colebourne |
|
* @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a> |
|
* @author Holger Krauth |
|
* @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a> |
|
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> |
|
* @author Arun Mammen Thomas |
|
* @author Gary Gregory |
|
* @author Phil Steitz |
|
* @author Al Chou |
|
* @author Michael Davey |
|
* @author Reuben Sivan |
|
* @author Chris Hyzer |
|
* @author Scott Johnson |
|
* @version $Id: helper.StringUtils.java 635447 2008-03-10 06:27:09Z bayard $ |
|
* @see java.lang.String |
|
* @since 1.0 |
|
*/ |
|
public class StringUtils { |
|
// Performance testing notes (JDK 1.4, Jul03, scolebourne) |
|
// Whitespace: |
|
// Character.isWhitespace() is faster than WHITESPACE.indexOf() |
|
// where WHITESPACE is a string of all whitespace characters |
|
// |
|
// Character access: |
|
// String.charAt(n) versus toCharArray(), then array[n] |
|
// String.charAt(n) is about 15% worse for a 10K string |
|
// They are about equal for a length 50 string |
|
// String.charAt(n) is about 4 times better for a length 3 string |
|
// String.charAt(n) is best bet overall |
|
// |
|
// Append: |
|
// String.concat about twice as fast as StringBuffer.append |
|
// (not sure who tested this) |
|
|
|
/** |
|
* 空字符串 |
|
*/ |
|
public static final String EMPTY = ""; |
|
|
|
/** |
|
* 空白字符串 |
|
*/ |
|
public static final String BLANK = " "; |
|
|
|
|
|
private StringUtils() { |
|
|
|
} |
|
|
|
/** |
|
* 生成一个非null的字符串 |
|
* |
|
* @param txt 原对象 |
|
* @return 非null的字符窜 |
|
*/ |
|
public static String alwaysNotNull(String txt) { |
|
|
|
return txt == null ? StringUtils.EMPTY : txt; |
|
} |
|
|
|
|
|
// Empty checks |
|
//----------------------------------------------------------------------- |
|
|
|
/** |
|
* <p>检查一个字符串是否是空字符串</p> |
|
* <p/> |
|
* <pre> |
|
* helper.StringUtils.isEmpty(null) = true |
|
* helper.StringUtils.isEmpty("") = true |
|
* helper.StringUtils.isEmpty(" ") = false |
|
* helper.StringUtils.isEmpty("bob") = false |
|
* helper.StringUtils.isEmpty(" bob ") = false |
|
* </pre> |
|
* <p/> |
|
* |
|
* @param str 被检查的字符串,可能为null |
|
* @return 如果字符串为空或者是null则返回true,否则返回false |
|
*/ |
|
public static boolean isEmpty(String str) { |
|
|
|
return str == null || str.length() == 0; |
|
} |
|
|
|
/** |
|
* <p>检查一个字符串是否不为空字符串</p> |
|
* <p/> |
|
* <pre> |
|
* helper.StringUtils.isNotEmpty(null) = false |
|
* helper.StringUtils.isNotEmpty("") = false |
|
* helper.StringUtils.isNotEmpty(" ") = true |
|
* helper.StringUtils.isNotEmpty("bob") = true |
|
* helper.StringUtils.isNotEmpty(" bob ") = true |
|
* </pre> |
|
* |
|
* @param str 被检查的字符串,可能是null |
|
* @return 如果字符串不为空且不是null则返回true,否则返回false |
|
*/ |
|
public static boolean isNotEmpty(String str) { |
|
|
|
return !StringUtils.isEmpty(str); |
|
} |
|
|
|
/** |
|
* <p>检查一个字符串是否为空白字符串</p> |
|
* <p/> |
|
* <pre> |
|
* helper.StringUtils.isBlank(null) = true |
|
* helper.StringUtils.isBlank("") = true |
|
* helper.StringUtils.isBlank(" ") = true |
|
* helper.StringUtils.isBlank("bob") = false |
|
* helper.StringUtils.isBlank(" bob ") = false |
|
* </pre> |
|
* |
|
* @param str 被检查的字符串 |
|
* @return 如果字符串为空、空格符或者null那么返回true,否则返回false |
|
*/ |
|
public static boolean isBlank(String str) { |
|
|
|
int strLen; |
|
return str == null || (strLen = str.length()) == 0 ? true : isBlank(str, strLen); |
|
} |
|
|
|
/** |
|
* for JIT |
|
*/ |
|
private static boolean isBlank(String str, int strLen) { |
|
|
|
for (int i = 0; i < strLen; i++) { |
|
if ((Character.isWhitespace(str.charAt(i)) == false)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
/** |
|
* 处理已A字符开头的字符,去除掉A |
|
* |
|
* @param org 原字符 |
|
* @param mark 标记字符 |
|
* @return 处理后的字符 |
|
*/ |
|
public static String cutStringStartWith(String org, String mark) { |
|
|
|
if (org == null) { |
|
return null; |
|
} |
|
|
|
if (mark == null) { |
|
return org; |
|
} |
|
if (!org.startsWith(mark)) { |
|
return org; |
|
} |
|
return org.substring(mark.length()); |
|
} |
|
|
|
/** |
|
* 1??某一个特定字符B结束的字符AB,得到去掉B的前面的字符A |
|
* |
|
* @param org 全部字符 |
|
* @param mark 标记B |
|
* @return 处理后的字符 |
|
*/ |
|
public static String cutStringEndWith(String org, String mark) { |
|
|
|
if (org == null) { |
|
return null; |
|
} |
|
|
|
if (mark == null) { |
|
return org; |
|
} |
|
|
|
if (!org.endsWith(mark)) { |
|
return org; |
|
} |
|
int location = org.indexOf(mark); |
|
if (location == -1) { |
|
return org; |
|
} |
|
return org.substring(0, location); |
|
} |
|
|
|
/** |
|
* <p>检查一个字符串是否不是空白字符串</p> |
|
* <p/> |
|
* <pre> |
|
* helper.StringUtils.isNotBlank(null) = false |
|
* helper.StringUtils.isNotBlank("") = false |
|
* helper.StringUtils.isNotBlank(" ") = false |
|
* helper.StringUtils.isNotBlank("bob") = true |
|
* helper.StringUtils.isNotBlank(" bob ") = true |
|
* </pre> |
|
* |
|
* @param str 被检查的字符串 |
|
* @return 如果字符串不是空字符串、空格符以及null那么就返回true,否则返回false |
|
*/ |
|
public static boolean isNotBlank(String str) { |
|
|
|
return !StringUtils.isBlank(str); |
|
} |
|
|
|
// Trim |
|
//----------------------------------------------------------------------- |
|
|
|
/** |
|
* <p>Removes control characters (char <= 32) from both |
|
* ends of this String, handling <code>null</code> by returning |
|
* <code>null</code>.</p> |
|
* <p/> |
|
* <p>The String is trimmed using {@link String#trim()}. |
|
* Trim removes start and end characters <= 32. |
|
* To strip whitespace use {@link #(String)}.</p> |
|
* <p/> |
|
* <p>To trim your choice of characters, use the |
|
* {@link #(String, String)} methods.</p> |
|
* <p/> |
|
* <pre> |
|
* helper.StringUtils.trim(null) = null |
|
* helper.StringUtils.trim("") = "" |
|
* helper.StringUtils.trim(" ") = "" |
|
* helper.StringUtils.trim("abc") = "abc" |
|
* helper.StringUtils.trim(" abc ") = "abc" |
|
* </pre> |
|
* |
|
* @param str the String to be trimmed, may be null |
|
* @return the trimmed string, <code>null</code> if null String input |
|
*/ |
|
public static String trim(String str) { |
|
|
|
return str == null ? null : str.trim(); |
|
} |
|
|
|
/** |
|
* 去掉字符串首尾的空白,如果剩余的结果是空白字符串那么返回null |
|
*/ |
|
public static String trimToNull(String str) { |
|
|
|
String ts = trim(str); |
|
return isEmpty(ts) ? null : ts; |
|
} |
|
|
|
/** |
|
* 检查一个字符串是否以某个指定的字符串开始,如果是的话不做改变,如果不是的话将把指定的字符串添加到原 |
|
* 字符串的起始位置 |
|
*/ |
|
public static String perfectStart(String str, String attach) { |
|
|
|
if (str == null) { |
|
return attach; |
|
} |
|
return str.startsWith(attach) ? str : (attach + str); |
|
} |
|
|
|
/** |
|
* 检查一个字符串是否以某个指定的字符串结束,如果是的话不做改变,如果不是的话将把指定的字符串添加到原 |
|
* 字符串的末尾位置 |
|
*/ |
|
public static String perfectEnd(String str, String attach) { |
|
|
|
if (str == null) { |
|
return attach; |
|
} |
|
return str.endsWith(attach) ? str : (str + attach); |
|
} |
|
|
|
public static String perfectSurround(String str, String attach) { |
|
|
|
if (str == null) { |
|
return attach; |
|
} |
|
str = str.endsWith(attach) ? str : (str + attach); |
|
str = str.startsWith(attach) ? str : (attach + str); |
|
|
|
return str; |
|
} |
|
|
|
/** |
|
* 获取字符串的长度,如果是null则返回0 |
|
*/ |
|
public static int getLength(String str) { |
|
|
|
return str == null ? 0 : str.length(); |
|
} |
|
|
|
/** |
|
* richer:判断两个字符串是否出去前后的附加字符串外是相等的 |
|
* eg:equalsIgnore("/File/", "File", "/") == true |
|
* 不支持传null path |
|
*/ |
|
public static boolean equalsIgnore(String str1, String str2, String attach) { |
|
if(str1 ==null || str2 == null) { |
|
throw new RuntimeException("null path"); |
|
} |
|
return equals(str1, str2) || perfectStart(perfectEnd(str1, attach), attach).equals(perfectStart(perfectEnd(str2, attach), attach)); |
|
} |
|
|
|
/** |
|
* 判断字符串text是否包含字符串ch |
|
* |
|
* @param text 主字符串 |
|
* @param ch 寻找的字符串 |
|
* @return 是否包含 |
|
* @date 2014-12-3-上午11:50:25 |
|
*/ |
|
public static boolean contains(String text, String ch) { |
|
|
|
return text != null && text.indexOf(ch) > -1; |
|
} |
|
|
|
/** |
|
* text 做兼容类. |
|
* |
|
* @param text 文本兼容 |
|
* @return StringTokenizer |
|
*/ |
|
public static StringTokenizer text2StringTokenizer(String text) { |
|
|
|
return new StringTokenizer(text, "\r\n"); |
|
} |
|
|
|
/** |
|
* carl:拼接数组字符 |
|
*/ |
|
public static String join(String seperator, String[] strings) { |
|
|
|
if (strings == null) { |
|
return null; |
|
} |
|
int length = strings.length; |
|
if (length == 0) { |
|
return ""; |
|
} |
|
StringBuffer buf = new StringBuffer(length * strings[0].length()) |
|
.append(strings[0]); |
|
for (int i = 1; i < length; i++) { |
|
buf.append(seperator).append(strings[i]); |
|
} |
|
return buf.toString(); |
|
} |
|
|
|
public static String parseVersion(String xmlDesignerVersion) { |
|
|
|
xmlDesignerVersion = xmlDesignerVersion.replace('A', '0'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('B', '1'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('C', '2'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('D', '3'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('E', '4'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('F', '5'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('G', '6'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('H', '7'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('I', '8'); |
|
xmlDesignerVersion = xmlDesignerVersion.replace('J', '9'); |
|
return xmlDesignerVersion; |
|
} |
|
|
|
/** |
|
* 是否是数组类型的字符串 |
|
* |
|
* @param text 目标字符串 |
|
* @return 是否是数组类型的字符串 |
|
*/ |
|
public static boolean isArrayType(String text) { |
|
|
|
return text != null && ((text.startsWith("[") && text.endsWith("]")) || (text.startsWith("[[") && text.endsWith("]]"))); |
|
} |
|
|
|
public static String[][] stringToArray(String v) { |
|
//[["华东","江苏"],["华东","上海"]] 或者 ["华东","江苏"] |
|
if (isArrayType(v)) { |
|
v = v.replaceAll("\"", ""); |
|
if (v.startsWith("[[") && v.endsWith("]]")) { |
|
String[] temp = (v.substring(2, v.length() - 2)).split("],\\["); |
|
String[][] strs = new String[temp.length][]; |
|
for (int i = 0; i < strs.length; i++) { |
|
strs[i] = temp[i].split(","); |
|
} |
|
return strs; |
|
} else { |
|
String[][] strs = new String[1][]; |
|
strs[0] = v.substring(1, v.length() - 1).split(","); |
|
return strs; |
|
} |
|
} else { |
|
//华东,江苏;华东,上海 |
|
String[] temp = v.split(";"); |
|
String[][] strs = new String[temp.length][]; |
|
for (int i = 0; i < strs.length; i++) { |
|
strs[i] = temp[i].split(","); |
|
} |
|
return strs; |
|
} |
|
} |
|
|
|
/** |
|
* 根据字节数截取字符串 |
|
* |
|
* @param originString 原始字符串 |
|
* @param charsetName 字符编码 |
|
* @param byteLength 字节长度 |
|
* @return 截取后的字符串 |
|
* @throws UnsupportedEncodingException |
|
*/ |
|
public static String subStringByByteLength(String originString, String charsetName, int byteLength) |
|
throws UnsupportedEncodingException { |
|
|
|
if (StringUtils.isBlank(originString) || byteLength <= 0) { |
|
return StringUtils.EMPTY; |
|
} |
|
char[] chars = originString.toCharArray(); |
|
int length = 0, index = chars.length; |
|
for (int i = 0; i < chars.length; i++) { |
|
final int len = String.valueOf(chars[i]).getBytes(charsetName).length + length; |
|
if (len <= byteLength) { |
|
length = len; |
|
} else { |
|
index = i; |
|
break; |
|
} |
|
} |
|
return String.valueOf(chars, 0, index); |
|
} |
|
|
|
|
|
/** |
|
* peter:比较相等. |
|
* |
|
* @param obj1 may be null. |
|
* @param obj2 may be null. |
|
*/ |
|
public static boolean equals(String obj1, String obj2) { |
|
|
|
if (obj1 == obj2) { |
|
return true; |
|
} |
|
if (obj1 == null || obj2 == null) { |
|
return false; |
|
} |
|
return obj1.equals(obj2); |
|
} |
|
|
|
/** |
|
* 不区分大小写比较字符串 |
|
*/ |
|
public static boolean equalsIgnoreCase(String s1, String s2) { |
|
|
|
if (s1 == null) { |
|
return s2 == null; |
|
} |
|
return s2 != null && s1.equalsIgnoreCase(s2); |
|
} |
|
|
|
/** |
|
* 右侧填充空格直到字符串达到指定长度 |
|
*/ |
|
public static String rightPad(String str, int size) { |
|
int len = size - str.length(); |
|
if (len <= 0) { |
|
return str; |
|
} |
|
char[] spaces = new char[len]; |
|
Arrays.fill(spaces, ' '); |
|
return str + String.valueOf(spaces); |
|
} |
|
} |