cn.felord.utils.StringUtils Maven / Gradle / Ivy
/*
* Copyright (c) 2023. felord.cn
* 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
* https://www.apache.org/licenses/LICENSE-2.0
* Website:
* https://felord.cn
* 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 cn.felord.utils;
/**
* Miscellaneous {@link String} utility methods.
*
* Mainly for internal use within the framework; consider
* Apache's Commons Lang
* for a more comprehensive suite of {@code String} utilities.
*
*
This class delivers some simple functionality that should really be
* provided by the core Java {@link String} and {@link StringBuilder}
* classes. It also provides easy-to-use methods to convert between
* delimited strings, such as CSV strings, and collections and arrays.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Keith Donald
* @author Rob Harrop
* @author Rick Evans
* @author Arjen Poutsma
* @author Sam Brannen
* @author Brian Clozel
* @since 16 April 2001
*/
public abstract class StringUtils {
private static final char FOLDER_SEPARATOR_CHAR = '/';
private static final char EXTENSION_SEPARATOR = '.';
/**
* Has length boolean.
*
* @param str the str
* @return the boolean
*/
public static boolean hasLength(CharSequence str) {
return (str != null && str.length() > 0);
}
/**
* Check that the given {@code String} is neither {@code null} nor of length 0.
*
Note: this method returns {@code true} for a {@code String} that
* purely consists of whitespace.
*
* @param str the {@code String} to check (may be {@code null})
* @return {@code true} if the {@code String} is not {@code null} and has length
* @see #hasLength(CharSequence) #hasLength(CharSequence)#hasLength(CharSequence)#hasLength(CharSequence)#hasLength(CharSequence)#hasLength(CharSequence)
* @see #hasText(String) #hasText(String)#hasText(String)#hasText(String)#hasText(String)#hasText(String)
*/
public static boolean hasLength(String str) {
return (str != null && !str.isEmpty());
}
/**
* Has text boolean.
*
* @param str the str
* @return the boolean
*/
public static boolean hasText(CharSequence str) {
return (str != null && str.length() > 0 && containsText(str));
}
/**
* Has text boolean.
*
* @param str the str
* @return the boolean
*/
public static boolean hasText(String str) {
return (str != null && !str.isEmpty() && containsText(str));
}
/**
* Has no text boolean.
*
* @param str the str
* @return the boolean
*/
public static boolean hasNoText(String str) {
return str == null || str.isEmpty() || !containsText(str);
}
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
/**
* Contains whitespace boolean.
*
* @param str the str
* @return the boolean
*/
public static boolean containsWhitespace(CharSequence str) {
if (!hasLength(str)) {
return false;
}
int strLen = str.length();
for (int i = 0; i < strLen; i++) {
if (Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
/**
* Contains whitespace boolean.
*
* @param str the str
* @return the boolean
*/
public static boolean containsWhitespace(String str) {
return containsWhitespace((CharSequence) str);
}
/**
* Trim whitespace string.
*
* @param str the str
* @return the string
*/
public static String trimWhitespace(String str) {
if (!hasLength(str)) {
return str;
}
int beginIndex = 0;
int endIndex = str.length() - 1;
while (beginIndex <= endIndex && Character.isWhitespace(str.charAt(beginIndex))) {
beginIndex++;
}
while (endIndex > beginIndex && Character.isWhitespace(str.charAt(endIndex))) {
endIndex--;
}
return str.substring(beginIndex, endIndex + 1);
}
/**
* Trim all whitespace char sequence.
*
* @param text the text
* @return the char sequence
*/
public static CharSequence trimAllWhitespace(CharSequence text) {
if (!hasLength(text)) {
return text;
}
int len = text.length();
StringBuilder sb = new StringBuilder(text.length());
for (int i = 0; i < len; i++) {
char c = text.charAt(i);
if (!Character.isWhitespace(c)) {
sb.append(c);
}
}
return sb.toString();
}
/**
* Trim all whitespace string.
*
* @param str the str
* @return the string
*/
public static String trimAllWhitespace(String str) {
if (str == null) {
return null;
}
return trimAllWhitespace((CharSequence) str).toString();
}
/**
* Trim leading whitespace string.
*
* @param str the str
* @return the string
*/
public static String trimLeadingWhitespace(String str) {
if (!hasLength(str)) {
return str;
}
int beginIdx = 0;
while (beginIdx < str.length() && Character.isWhitespace(str.charAt(beginIdx))) {
beginIdx++;
}
return str.substring(beginIdx);
}
/**
* Trim trailing whitespace string.
*
* @param str the str
* @return the string
*/
public static String trimTrailingWhitespace(String str) {
if (!hasLength(str)) {
return str;
}
int endIdx = str.length() - 1;
while (endIdx >= 0 && Character.isWhitespace(str.charAt(endIdx))) {
endIdx--;
}
return str.substring(0, endIdx + 1);
}
/**
* Trim leading character string.
*
* @param str the str
* @param leadingCharacter the leading character
* @return the string
*/
public static String trimLeadingCharacter(String str, char leadingCharacter) {
if (!hasLength(str)) {
return str;
}
int beginIdx = 0;
while (beginIdx < str.length() && leadingCharacter == str.charAt(beginIdx)) {
beginIdx++;
}
return str.substring(beginIdx);
}
/**
* Trim trailing character string.
*
* @param str the str
* @param trailingCharacter the trailing character
* @return the string
*/
public static String trimTrailingCharacter(String str, char trailingCharacter) {
if (!hasLength(str)) {
return str;
}
int endIdx = str.length() - 1;
while (endIdx >= 0 && trailingCharacter == str.charAt(endIdx)) {
endIdx--;
}
return str.substring(0, endIdx + 1);
}
/**
* Matches character boolean.
*
* @param str the str
* @param singleCharacter the single character
* @return the boolean
*/
public static boolean matchesCharacter(String str, char singleCharacter) {
return (str != null && str.length() == 1 && str.charAt(0) == singleCharacter);
}
/**
* Starts with ignore case boolean.
*
* @param str the str
* @param prefix the prefix
* @return the boolean
*/
public static boolean startsWithIgnoreCase(String str, String prefix) {
return (str != null && prefix != null && str.length() >= prefix.length() &&
str.regionMatches(true, 0, prefix, 0, prefix.length()));
}
/**
* Ends with ignore case boolean.
*
* @param str the str
* @param suffix the suffix
* @return the boolean
*/
public static boolean endsWithIgnoreCase(String str, String suffix) {
return (str != null && suffix != null && str.length() >= suffix.length() &&
str.regionMatches(true, str.length() - suffix.length(), suffix, 0, suffix.length()));
}
/**
* Substring match boolean.
*
* @param str the str
* @param index the index
* @param substring the substring
* @return the boolean
*/
public static boolean substringMatch(CharSequence str, int index, CharSequence substring) {
if (index + substring.length() > str.length()) {
return false;
}
for (int i = 0; i < substring.length(); i++) {
if (str.charAt(index + i) != substring.charAt(i)) {
return false;
}
}
return true;
}
/**
* Count occurrences of int.
*
* @param str the str
* @param sub the sub
* @return the int
*/
public static int countOccurrencesOf(String str, String sub) {
if (!hasLength(str) || !hasLength(sub)) {
return 0;
}
int count = 0;
int pos = 0;
int idx;
while ((idx = str.indexOf(sub, pos)) != -1) {
++count;
pos = idx + sub.length();
}
return count;
}
/**
* Replace string.
*
* @param inString the in string
* @param oldPattern the old pattern
* @param newPattern the new pattern
* @return the string
*/
public static String replace(String inString, String oldPattern, String newPattern) {
if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) {
return inString;
}
int index = inString.indexOf(oldPattern);
if (index == -1) {
// no occurrence -> can return input as-is
return inString;
}
int capacity = inString.length();
if (newPattern.length() > oldPattern.length()) {
capacity += 16;
}
StringBuilder sb = new StringBuilder(capacity);
int pos = 0; // our position in the old string
int patLen = oldPattern.length();
while (index >= 0) {
sb.append(inString, pos, index);
sb.append(newPattern);
pos = index + patLen;
index = inString.indexOf(oldPattern, pos);
}
// append any characters to the right of a match
sb.append(inString, pos, inString.length());
return sb.toString();
}
/**
* Delete string.
*
* @param inString the in string
* @param pattern the pattern
* @return the string
*/
public static String delete(String inString, String pattern) {
return replace(inString, pattern, "");
}
/**
* Delete any string.
*
* @param inString the in string
* @param charsToDelete the chars to delete
* @return the string
*/
public static String deleteAny(String inString, String charsToDelete) {
if (!hasLength(inString) || !hasLength(charsToDelete)) {
return inString;
}
int lastCharIndex = 0;
char[] result = new char[inString.length()];
for (int i = 0; i < inString.length(); i++) {
char c = inString.charAt(i);
if (charsToDelete.indexOf(c) == -1) {
result[lastCharIndex++] = c;
}
}
if (lastCharIndex == inString.length()) {
return inString;
}
return new String(result, 0, lastCharIndex);
}
/**
* Quote string.
*
* @param str the str
* @return the string
*/
public static String quote(String str) {
return (str != null ? "'" + str + "'" : null);
}
/**
* Quote if string object.
*
* @param obj the obj
* @return the object
*/
public static Object quoteIfString(Object obj) {
return (obj instanceof String ? quote((String) obj) : obj);
}
/**
* Unqualify string.
*
* @param qualifiedName the qualified name
* @return the string
*/
public static String unqualify(String qualifiedName) {
return unqualify(qualifiedName, '.');
}
/**
* Unqualify string.
*
* @param qualifiedName the qualified name
* @param separator the separator
* @return the string
*/
public static String unqualify(String qualifiedName, char separator) {
return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1);
}
/**
* Capitalize string.
*
* @param str the str
* @return the string
*/
public static String capitalize(String str) {
return changeFirstCharacterCase(str, true);
}
/**
* Uncapitalize string.
*
* @param str the str
* @return the string
*/
public static String uncapitalize(String str) {
return changeFirstCharacterCase(str, false);
}
private static String changeFirstCharacterCase(String str, boolean capitalize) {
if (!hasLength(str)) {
return str;
}
char baseChar = str.charAt(0);
char updatedChar;
if (capitalize) {
updatedChar = Character.toUpperCase(baseChar);
} else {
updatedChar = Character.toLowerCase(baseChar);
}
if (baseChar == updatedChar) {
return str;
}
char[] chars = str.toCharArray();
chars[0] = updatedChar;
return new String(chars);
}
/**
* Gets filename.
*
* @param path the path
* @return the filename
*/
public static String getFilename(String path) {
if (path == null) {
return null;
}
int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR);
return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path);
}
/**
* Gets filename extension.
*
* @param path the path
* @return the filename extension
*/
public static String getFilenameExtension(String path) {
if (path == null) {
return null;
}
int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
if (extIndex == -1) {
return null;
}
int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR);
if (folderIndex > extIndex) {
return null;
}
return path.substring(extIndex + 1);
}
/**
* Strip filename extension string.
*
* @param path the path
* @return the string
*/
public static String stripFilenameExtension(String path) {
int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
if (extIndex == -1) {
return path;
}
int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR_CHAR);
if (folderIndex > extIndex) {
return path;
}
return path.substring(0, extIndex);
}
}