package com.cyksj.common.util; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author chan 字符串操作辅助类 **/ public final class StringUtil { /** * Linux and macOS. */ private static final String LF = "\n"; /** * Classic macOS. */ private static final String CR = "\r"; /** * Windows. */ private static final String CRLF = "\r\n"; /** * An empty immutable {@code String} array. */ public static final String[] EMPTY_STRING_ARRAY = new String[0]; public static final String EMPTY = ""; public static final String randomStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#&/_-"; private static final String baseStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /** * provate constructor */ private StringUtil() { } // Empty checks //----------------------------------------------------------------------- /** *

Checks if a CharSequence is empty ("") or null.

* *
	 * Strings.isEmpty(null)      = true
	 * Strings.isEmpty("")        = true
	 * Strings.isEmpty(" ")       = false
	 * Strings.isEmpty("bob")     = false
	 * Strings.isEmpty("  bob  ") = false
	 * 
* *

NOTE: This method changed in Lang version 2.0. * It no longer trims the CharSequence. * That functionality is available in isBlank().

* * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is empty or null */ public static boolean isEmpty(final String cs) { return cs == null || cs.isEmpty(); } /** *

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

* *
	 * Strings.isNotEmpty(null)      = false
	 * Strings.isNotEmpty("")        = false
	 * Strings.isNotEmpty(" ")       = true
	 * Strings.isNotEmpty("bob")     = true
	 * Strings.isNotEmpty("  bob  ") = true
	 * 
* * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is not empty and not null */ public static boolean isNotEmpty(final String cs) { return !isEmpty(cs); } /** *

Checks if a CharSequence is empty (""), null or whitespace only.

* *

Whitespace is defined by {@link Character#isWhitespace(char)}.

* *
	 * Strings.isBlank(null)      = true
	 * Strings.isBlank("")        = true
	 * Strings.isBlank(" ")       = true
	 * Strings.isBlank("bob")     = false
	 * Strings.isBlank("  bob  ") = false
	 * 
* * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is null, empty or whitespace only */ public static boolean isBlank(final String cs) { return cs == null || cs.isBlank(); } /** *

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

* *

Whitespace is defined by {@link Character#isWhitespace(char)}.

* *
	 * Strings.isNotBlank(null)      = false
	 * Strings.isNotBlank("")        = false
	 * Strings.isNotBlank(" ")       = false
	 * Strings.isNotBlank("bob")     = true
	 * Strings.isNotBlank("  bob  ") = true
	 * 
* * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is * not empty and not null and not whitespace only */ public static boolean isNotBlank(final String cs) { return !isBlank(cs); } /** *

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
	 * 
* * @param cs1 the first CharSequence, may be {@code null} * @param cs2 the second CharSequence, may be {@code null} * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} */ public static boolean equals(final String cs1, final String cs2) { if (cs1 == null && cs2 == null) { return true; } if (cs1 == null || cs2 == null) { return false; } if (cs1.length() != cs2.length()) { return false; } return cs1.equals(cs2); } /** *

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. The 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
	 * 
* * @param cs1 the first CharSequence, may be {@code null} * @param cs2 the second CharSequence, may be {@code null} * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null} */ public static boolean equalsIgnoreCase(final String cs1, final String cs2) { if (cs1 == null && cs2 == null) { return true; } if (cs1 == null || cs2 == null) { return false; } if (cs1.length() != cs2.length()) { return false; } return cs1.equalsIgnoreCase(cs2); } /** *

Check if a CharSequence 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 String#startsWith(String) * @param str the CharSequence to check, may be null * @param prefix the prefix to find, may be null * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or * both {@code null} */ public static boolean startsWith(final String str, final String prefix) { if (null == str && prefix == null) { return true; } if (null == str || prefix == null) { return false; } return str.startsWith(prefix); } /** *

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

* * @see String#endsWith(String) * @param str the CharSequence to check, may be null * @param suffix the suffix to find, may be null * @return {@code true} if the CharSequence starts with the prefix or * both {@code null} */ public static boolean endsWith(final String str, final String suffix) { if (null == str && suffix == null) { return true; } if (null == str || suffix == null) { return false; } return str.endsWith(suffix); } /** * Performs the logic for the {@code split} and * {@code splitPreserveAllTokens} methods that do not return a * maximum array length. * * @param str the String to parse, may be {@code null} * @param separatorChar the separate character * @return an array of parsed Strings, {@code null} if null String input */ public static String[] split(final String str, final char separatorChar) { // Performance tuned for 2.0 (JDK1.4) if (str == null) { return null; } final int len = str.length(); if (len == 0) { return EMPTY_STRING_ARRAY; } final List list = new ArrayList<>(); int i = 0, start = 0; boolean match = false; while (i < len) { if (str.charAt(i) == separatorChar) { if (match) { list.add(str.substring(start, i)); match = false; } start = ++i; continue; } match = true; i++; } if (match) { list.add(str.substring(start, i)); } return list.toArray(new String[list.size()]); } /** * Performs the logic for the {@code split} and * {@code splitPreserveAllTokens} methods that return a maximum array * length. * * @param str the String to parse, may be {@code null} * @param separatorChars the separate character * @return an array of parsed Strings, {@code null} if null String input */ public static String[] split(final String str, final String separatorChars) { // Performance tuned for 2.0 (JDK1.4) // Direct code is quicker than StringTokenizer. // Also, StringTokenizer uses isSpace() not isWhitespace() if (str == null) { return null; } final int len = str.length(); if (len == 0) { return EMPTY_STRING_ARRAY; } final List list = new ArrayList<>(); int sizePlus1 = 1; int i = 0, start = 0; boolean match = false; final int max = -1; if (separatorChars == null) { // Null separator means use whitespace while (i < len) { if (Character.isWhitespace(str.charAt(i))) { if (match) { if (sizePlus1++ == max) { i = len; } list.add(str.substring(start, i)); match = false; } start = ++i; continue; } match = true; i++; } } else if (separatorChars.length() == 1) { // Optimise 1 character case final char sep = separatorChars.charAt(0); while (i < len) { if (str.charAt(i) == sep) { if (match) { if (sizePlus1++ == max) { i = len; } list.add(str.substring(start, i)); match = false; } start = ++i; continue; } match = true; i++; } } else { // standard case while (i < len) { if (separatorChars.indexOf(str.charAt(i)) >= 0) { if (match) { if (sizePlus1++ == max) { i = len; } list.add(str.substring(start, i)); match = false; } start = ++i; continue; } match = true; i++; } } if (match) { list.add(str.substring(start, i)); } return list.toArray(new String[list.size()]); } /** * @author chan * @param obj 需要转换的对象 * @return string **/ public static String getString(Object obj) { if (obj == null) { return EMPTY; } else { return obj.toString(); } } /** * @author chan 异常栈字符串输出 * @param throwable ex * @return String **/ public static String getErrorText(Throwable throwable) { if (throwable == null) { return "ERROR,throwable is NULL!"; } try (StringWriter strWriter = new StringWriter(512); PrintWriter writer = new PrintWriter(strWriter)) { throwable.printStackTrace(writer); StringBuffer sb = strWriter.getBuffer(); return sb.toString(); } catch (Exception ex) { return "ERROR!"; } } public static String getErrorMsg(Throwable throwable) { if (throwable == null) { return "ERROR,throwable is NULL!"; } String message = throwable.getMessage(); return message; } /** * 随即获取length随机字符串 */ public static void getRandomStr(StringBuilder sb, Integer length) { Integer baseLength = randomStr.length(); for (int i = 0; i < length; i++) { int number = RandomUtil.randomInt(baseLength); sb.append(randomStr.charAt(number)); } } public static String randomString(Integer length) { if (length == null || length < 0) { length = 6; } Integer baseLength = baseStr.length(); StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) { int number = RandomUtil.randomInt(baseLength); sb.append(randomStr.charAt(number)); } return sb.toString(); } /** * 生成4位\6位随机数 */ public static String getRandomCodeStr(Integer digit) { if (null == digit) { digit = 6; } String code; // 生成验证码 if (digit == 4) { code = new Random().nextInt(8999) + 1000 + ""; } else { code = new Random().nextInt(899999) + 100000 + ""; } return code; } /** * 姓名匿名 */ public static String anonymity(char[] name) { final int size = name.length; char[] chars = new char[3]; if (size == 1 || size == 2) { chars[0] = '*'; chars[1] = ' '; chars[2] = name[size - 1]; } else { chars[0] = '*'; chars[1] = name[size - 2]; chars[2] = name[size - 1]; } return new String(chars); } public static String getRealAddressByIP(String ip) { if (StrUtil.isBlank(ip)) { return "unknown"; } try { String rspStr = HttpUtil.get("http://whois.pconline.com.cn/ipJson.jsp?ip=" + ip + "&json=true"); if (StrUtil.isEmpty(rspStr)) { return "unknown"; } JSONObject obj = JSONUtil.parseObj(rspStr); String region = obj.getStr("pro"); String city = obj.getStr("city"); return String.format("%s %s", region, city); } catch (Exception e) { } return "unknown"; } /** * 获取账号登录验证码 */ public static String getVerifyCodePattern(String code, Integer length) { if (StrUtil.isNotEmpty(code)) { Pattern pattern = Pattern.compile(String.format("\\d{%s,}", length)); Matcher matcher = pattern.matcher(code); while (matcher.find()) { return matcher.group(); } } return StrUtil.EMPTY; } }