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 com.cyksj.dto.ArkIpAddressDto;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.http.HttpResponse;
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";
public static final String QM = "?";
public static final String AD = "&";
/**
* 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";
private static final String PAID_IP_APP_CODE_AUTH = "APPCODE ce891b0008634139a493d477c064ff19";
/**
* 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(baseStr.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 java.security.SecureRandom().nextInt(9000) + 1000 + "";
} else {
code = new java.security.SecureRandom().nextInt(900000) + 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 url = String.format("http://whois.pconline.com.cn/ipJson.jsp?ip=%s" + "&json=true", ip);
HttpResponse send = J11HttpC
.custom().ofGet().url(url)
.send(HttpResponse.BodyHandlers.ofString());
String rspStr = send.body();
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 getInternalAddressByIP(String ip) {
if (StrUtil.isBlank(ip)) {
return "unknown";
}
try {
String url = String.format("http://whois.pconline.com.cn/ipJson.jsp?ip=%s" + "&json=true", ip);
HttpResponse send = J11HttpC
.custom().ofGet().url(url)
.send(HttpResponse.BodyHandlers.ofString());
String rspStr = send.body();
if (StrUtil.isEmpty(rspStr)) {
return "unknown";
}
JSONObject obj = JSONUtil.parseObj(rspStr);
String addr = obj.getStr("addr");
return addr;
} catch (Exception e) {
}
return "unknown";
}
/**
* 付费ip地址查询
*/
public static String getNewestIpAddress(String ip) {
cn.hutool.http.HttpResponse execute = HttpUtil.createGet(String.format("https://ipaddr.market.alicloudapi.com/ip_addr_search/v1?IP_ADDR=%s", ip))
.header("Authorization", PAID_IP_APP_CODE_AUTH)
.header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
.execute();
try {
ArkIpAddressDto arkIpAddressDto = Jsons.parseObject(execute.body(), ArkIpAddressDto.class);
ArkIpAddressDto.Entity.InputIpAddress inputIpAddress = arkIpAddressDto.getEntity().getInputIpAddress();
return inputIpAddress.getCity();
} catch (Exception e) {
}
return "unknown";
}
/**
* 身份证号返回
*/
public static String enIndent(String ident) {
String front = ident.substring(0, 4);
String back = ident.substring(ident.length() - 4);
StringBuilder sb = new StringBuilder();
sb.append(front).append("****").append(back);
return sb.toString();
}
public static String getNewInternalAddressByIp(String ip) {
if (StrUtil.isBlank(ip)) {
return "unknown";
}
try {
String url = String.format("https://searchplugin.csdn.net/api/v1/ip/get?ip=%s", ip);
HttpResponse send = J11HttpC
.custom().ofGet().url(url)
.send(HttpResponse.BodyHandlers.ofString());
String rspStr = send.body();
if (StrUtil.isEmpty(rspStr)) {
return "unknown";
}
JSONObject obj = JSONUtil.parseObj(rspStr);
JSONObject data = JSONUtil.parseObj(obj.get("data"));
String addr = data.getStr("address");
return addr;
} 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;
}
public static List> averageAssign(List source, int n) {
List> result = new ArrayList>();
int remainder = source.size() % n; //(先计算出余数)
int number = source.size() / n; //然后是商
int offset = 0;//偏移量
for (int i = 0; i < n; i++) {
List value = null;
if (remainder > 0) {
value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
remainder--;
offset++;
} else {
value = source.subList(i * number + offset, (i + 1) * number + offset);
}
result.add(value);
}
return result;
}
/**
* 付费ip地址查询
*/
public static String paidIpAddress(String ip) {
cn.hutool.http.HttpResponse execute = HttpUtil.createGet(String.format("https://ipaddr.market.alicloudapi.com/ip_addr_search/v1?IP_ADDR=%s", ip))
.header("Authorization", PAID_IP_APP_CODE_AUTH)
.header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
.execute();
try {
ArkIpAddressDto arkIpAddressDto = Jsons.parseObject(execute.body(), ArkIpAddressDto.class);
ArkIpAddressDto.Entity.InputIpAddress inputIpAddress = arkIpAddressDto.getEntity().getInputIpAddress();
return new StringBuilder()
.append(inputIpAddress.getNation())
.append(inputIpAddress.getProvince())
.append(inputIpAddress.getCity()).toString();
} catch (Exception e) {
}
return "unknown";
}
/**
* 姓名返回
*/
public static String enName(String name) {
String first = name.substring(0, 1);
if (name.length() <= 2) {
return first + "*";
}
String end = name.substring(name.length() - 1);
StringBuilder sb = new StringBuilder();
sb.append(first).append("*").append(end);
return sb.toString();
}
}