StringUtil.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. package com.cyksj.common.util;
  2. import cn.hutool.core.util.RandomUtil;
  3. import cn.hutool.core.util.StrUtil;
  4. import cn.hutool.http.HttpUtil;
  5. import cn.hutool.json.JSONObject;
  6. import cn.hutool.json.JSONUtil;
  7. import com.cyksj.dto.ArkIpAddressDto;
  8. import java.io.PrintWriter;
  9. import java.io.StringWriter;
  10. import java.net.http.HttpResponse;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import java.util.Random;
  14. import java.util.regex.Matcher;
  15. import java.util.regex.Pattern;
  16. /**
  17. * @author chan 字符串操作辅助类
  18. **/
  19. public final class StringUtil {
  20. /**
  21. * Linux and macOS.
  22. */
  23. private static final String LF = "\n";
  24. /**
  25. * Classic macOS.
  26. */
  27. private static final String CR = "\r";
  28. /**
  29. * Windows.
  30. */
  31. private static final String CRLF = "\r\n";
  32. public static final String QM = "?";
  33. public static final String AD = "&";
  34. /**
  35. * An empty immutable {@code String} array.
  36. */
  37. public static final String[] EMPTY_STRING_ARRAY = new String[0];
  38. public static final String EMPTY = "";
  39. public static final String randomStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  40. private static final String baseStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  41. private static final String PAID_IP_APP_CODE_AUTH = "APPCODE ce891b0008634139a493d477c064ff19";
  42. /**
  43. * provate constructor
  44. */
  45. private StringUtil() { }
  46. // Empty checks
  47. //-----------------------------------------------------------------------
  48. /**
  49. * <p>Checks if a CharSequence is empty ("") or null.</p>
  50. *
  51. * <pre>
  52. * Strings.isEmpty(null) = true
  53. * Strings.isEmpty("") = true
  54. * Strings.isEmpty(" ") = false
  55. * Strings.isEmpty("bob") = false
  56. * Strings.isEmpty(" bob ") = false
  57. * </pre>
  58. *
  59. * <p>NOTE: This method changed in Lang version 2.0.
  60. * It no longer trims the CharSequence.
  61. * That functionality is available in isBlank().</p>
  62. *
  63. * @param cs the CharSequence to check, may be null
  64. * @return {@code true} if the CharSequence is empty or null
  65. */
  66. public static boolean isEmpty(final String cs) {
  67. return cs == null || cs.isEmpty();
  68. }
  69. /**
  70. * <p>Checks if a CharSequence is not empty ("") and not null.</p>
  71. *
  72. * <pre>
  73. * Strings.isNotEmpty(null) = false
  74. * Strings.isNotEmpty("") = false
  75. * Strings.isNotEmpty(" ") = true
  76. * Strings.isNotEmpty("bob") = true
  77. * Strings.isNotEmpty(" bob ") = true
  78. * </pre>
  79. *
  80. * @param cs the CharSequence to check, may be null
  81. * @return {@code true} if the CharSequence is not empty and not null
  82. */
  83. public static boolean isNotEmpty(final String cs) {
  84. return !isEmpty(cs);
  85. }
  86. /**
  87. * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
  88. *
  89. * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  90. *
  91. * <pre>
  92. * Strings.isBlank(null) = true
  93. * Strings.isBlank("") = true
  94. * Strings.isBlank(" ") = true
  95. * Strings.isBlank("bob") = false
  96. * Strings.isBlank(" bob ") = false
  97. * </pre>
  98. *
  99. * @param cs the CharSequence to check, may be null
  100. * @return {@code true} if the CharSequence is null, empty or whitespace only
  101. */
  102. public static boolean isBlank(final String cs) {
  103. return cs == null || cs.isBlank();
  104. }
  105. /**
  106. * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
  107. *
  108. * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  109. *
  110. * <pre>
  111. * Strings.isNotBlank(null) = false
  112. * Strings.isNotBlank("") = false
  113. * Strings.isNotBlank(" ") = false
  114. * Strings.isNotBlank("bob") = true
  115. * Strings.isNotBlank(" bob ") = true
  116. * </pre>
  117. *
  118. * @param cs the CharSequence to check, may be null
  119. * @return {@code true} if the CharSequence is
  120. * not empty and not null and not whitespace only
  121. */
  122. public static boolean isNotBlank(final String cs) {
  123. return !isBlank(cs);
  124. }
  125. /**
  126. * <p>Compares two CharSequences, returning {@code true} if they represent
  127. * equal sequences of characters.</p>
  128. *
  129. * <p>{@code null}s are handled without exceptions. Two {@code null}
  130. * references are considered to be equal. The comparison is <strong>case sensitive</strong>.</p>
  131. *
  132. * <pre>
  133. * StringUtils.equals(null, null) = true
  134. * StringUtils.equals(null, "abc") = false
  135. * StringUtils.equals("abc", null) = false
  136. * StringUtils.equals("abc", "abc") = true
  137. * StringUtils.equals("abc", "ABC") = false
  138. * </pre>
  139. *
  140. * @param cs1 the first CharSequence, may be {@code null}
  141. * @param cs2 the second CharSequence, may be {@code null}
  142. * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
  143. */
  144. public static boolean equals(final String cs1, final String cs2) {
  145. if (cs1 == null && cs2 == null) {
  146. return true;
  147. }
  148. if (cs1 == null || cs2 == null) {
  149. return false;
  150. }
  151. if (cs1.length() != cs2.length()) {
  152. return false;
  153. }
  154. return cs1.equals(cs2);
  155. }
  156. /**
  157. * <p>Compares two CharSequences, returning {@code true} if they represent
  158. * equal sequences of characters, ignoring case.</p>
  159. *
  160. * <p>{@code null}s are handled without exceptions. Two {@code null}
  161. * references are considered equal. The comparison is <strong>case insensitive</strong>.</p>
  162. *
  163. * <pre>
  164. * StringUtils.equalsIgnoreCase(null, null) = true
  165. * StringUtils.equalsIgnoreCase(null, "abc") = false
  166. * StringUtils.equalsIgnoreCase("abc", null) = false
  167. * StringUtils.equalsIgnoreCase("abc", "abc") = true
  168. * StringUtils.equalsIgnoreCase("abc", "ABC") = true
  169. * </pre>
  170. *
  171. * @param cs1 the first CharSequence, may be {@code null}
  172. * @param cs2 the second CharSequence, may be {@code null}
  173. * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
  174. */
  175. public static boolean equalsIgnoreCase(final String cs1, final String cs2) {
  176. if (cs1 == null && cs2 == null) {
  177. return true;
  178. }
  179. if (cs1 == null || cs2 == null) {
  180. return false;
  181. }
  182. if (cs1.length() != cs2.length()) {
  183. return false;
  184. }
  185. return cs1.equalsIgnoreCase(cs2);
  186. }
  187. /**
  188. * <p>Check if a CharSequence starts with a specified prefix.</p>
  189. *
  190. * <p>{@code null}s are handled without exceptions. Two {@code null}
  191. * references are considered to be equal. The comparison is case sensitive.</p>
  192. *
  193. * <pre>
  194. * StringUtils.startsWith(null, null) = true
  195. * StringUtils.startsWith(null, "abc") = false
  196. * StringUtils.startsWith("abcdef", null) = false
  197. * StringUtils.startsWith("abcdef", "abc") = true
  198. * StringUtils.startsWith("ABCDEF", "abc") = false
  199. * </pre>
  200. *
  201. * @see String#startsWith(String)
  202. * @param str the CharSequence to check, may be null
  203. * @param prefix the prefix to find, may be null
  204. * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
  205. * both {@code null}
  206. */
  207. public static boolean startsWith(final String str, final String prefix) {
  208. if (null == str && prefix == null) {
  209. return true;
  210. }
  211. if (null == str || prefix == null) {
  212. return false;
  213. }
  214. return str.startsWith(prefix);
  215. }
  216. /**
  217. * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p>
  218. *
  219. * @see String#endsWith(String)
  220. * @param str the CharSequence to check, may be null
  221. * @param suffix the suffix to find, may be null
  222. * @return {@code true} if the CharSequence starts with the prefix or
  223. * both {@code null}
  224. */
  225. public static boolean endsWith(final String str, final String suffix) {
  226. if (null == str && suffix == null) {
  227. return true;
  228. }
  229. if (null == str || suffix == null) {
  230. return false;
  231. }
  232. return str.endsWith(suffix);
  233. }
  234. /**
  235. * Performs the logic for the {@code split} and
  236. * {@code splitPreserveAllTokens} methods that do not return a
  237. * maximum array length.
  238. *
  239. * @param str the String to parse, may be {@code null}
  240. * @param separatorChar the separate character
  241. * @return an array of parsed Strings, {@code null} if null String input
  242. */
  243. public static String[] split(final String str, final char separatorChar) {
  244. // Performance tuned for 2.0 (JDK1.4)
  245. if (str == null) {
  246. return null;
  247. }
  248. final int len = str.length();
  249. if (len == 0) {
  250. return EMPTY_STRING_ARRAY;
  251. }
  252. final List<String> list = new ArrayList<>();
  253. int i = 0, start = 0;
  254. boolean match = false;
  255. while (i < len) {
  256. if (str.charAt(i) == separatorChar) {
  257. if (match) {
  258. list.add(str.substring(start, i));
  259. match = false;
  260. }
  261. start = ++i;
  262. continue;
  263. }
  264. match = true;
  265. i++;
  266. }
  267. if (match) {
  268. list.add(str.substring(start, i));
  269. }
  270. return list.toArray(new String[list.size()]);
  271. }
  272. /**
  273. * Performs the logic for the {@code split} and
  274. * {@code splitPreserveAllTokens} methods that return a maximum array
  275. * length.
  276. *
  277. * @param str the String to parse, may be {@code null}
  278. * @param separatorChars the separate character
  279. * @return an array of parsed Strings, {@code null} if null String input
  280. */
  281. public static String[] split(final String str, final String separatorChars) {
  282. // Performance tuned for 2.0 (JDK1.4)
  283. // Direct code is quicker than StringTokenizer.
  284. // Also, StringTokenizer uses isSpace() not isWhitespace()
  285. if (str == null) {
  286. return null;
  287. }
  288. final int len = str.length();
  289. if (len == 0) {
  290. return EMPTY_STRING_ARRAY;
  291. }
  292. final List<String> list = new ArrayList<>();
  293. int sizePlus1 = 1;
  294. int i = 0, start = 0;
  295. boolean match = false;
  296. final int max = -1;
  297. if (separatorChars == null) {
  298. // Null separator means use whitespace
  299. while (i < len) {
  300. if (Character.isWhitespace(str.charAt(i))) {
  301. if (match) {
  302. if (sizePlus1++ == max) {
  303. i = len;
  304. }
  305. list.add(str.substring(start, i));
  306. match = false;
  307. }
  308. start = ++i;
  309. continue;
  310. }
  311. match = true;
  312. i++;
  313. }
  314. } else if (separatorChars.length() == 1) {
  315. // Optimise 1 character case
  316. final char sep = separatorChars.charAt(0);
  317. while (i < len) {
  318. if (str.charAt(i) == sep) {
  319. if (match) {
  320. if (sizePlus1++ == max) {
  321. i = len;
  322. }
  323. list.add(str.substring(start, i));
  324. match = false;
  325. }
  326. start = ++i;
  327. continue;
  328. }
  329. match = true;
  330. i++;
  331. }
  332. } else {
  333. // standard case
  334. while (i < len) {
  335. if (separatorChars.indexOf(str.charAt(i)) >= 0) {
  336. if (match) {
  337. if (sizePlus1++ == max) {
  338. i = len;
  339. }
  340. list.add(str.substring(start, i));
  341. match = false;
  342. }
  343. start = ++i;
  344. continue;
  345. }
  346. match = true;
  347. i++;
  348. }
  349. }
  350. if (match) {
  351. list.add(str.substring(start, i));
  352. }
  353. return list.toArray(new String[list.size()]);
  354. }
  355. /**
  356. * @author chan
  357. * @param obj 需要转换的对象
  358. * @return string
  359. **/
  360. public static String getString(Object obj) {
  361. if (obj == null) {
  362. return EMPTY;
  363. } else {
  364. return obj.toString();
  365. }
  366. }
  367. /**
  368. * @author chan 异常栈字符串输出
  369. * @param throwable ex
  370. * @return String
  371. **/
  372. public static String getErrorText(Throwable throwable) {
  373. if (throwable == null) {
  374. return "ERROR,throwable is NULL!";
  375. }
  376. try (StringWriter strWriter = new StringWriter(512); PrintWriter writer = new PrintWriter(strWriter)) {
  377. throwable.printStackTrace(writer);
  378. StringBuffer sb = strWriter.getBuffer();
  379. return sb.toString();
  380. } catch (Exception ex) {
  381. return "ERROR!";
  382. }
  383. }
  384. public static String getErrorMsg(Throwable throwable) {
  385. if (throwable == null) {
  386. return "ERROR,throwable is NULL!";
  387. }
  388. String message = throwable.getMessage();
  389. return message;
  390. }
  391. /**
  392. * 随即获取length随机字符串
  393. */
  394. public static void getRandomStr(StringBuilder sb, Integer length) {
  395. Integer baseLength = randomStr.length();
  396. for (int i = 0; i < length; i++) {
  397. int number = RandomUtil.randomInt(baseLength);
  398. sb.append(randomStr.charAt(number));
  399. }
  400. }
  401. public static String randomString(Integer length) {
  402. if (length == null || length < 0) {
  403. length = 6;
  404. }
  405. Integer baseLength = baseStr.length();
  406. StringBuilder sb = new StringBuilder(length);
  407. for (int i = 0; i < length; i++) {
  408. int number = RandomUtil.randomInt(baseLength);
  409. sb.append(baseStr.charAt(number));
  410. }
  411. return sb.toString();
  412. }
  413. /**
  414. * 生成4位\6位随机数
  415. */
  416. public static String getRandomCodeStr(Integer digit) {
  417. if (null == digit) {
  418. digit = 6;
  419. }
  420. String code;
  421. // 生成验证码
  422. if (digit == 4) {
  423. code = new java.security.SecureRandom().nextInt(9000) + 1000 + "";
  424. } else {
  425. code = new java.security.SecureRandom().nextInt(900000) + 100000 + "";
  426. }
  427. return code;
  428. }
  429. /**
  430. * 姓名匿名
  431. */
  432. public static String anonymity(char[] name) {
  433. final int size = name.length;
  434. char[] chars = new char[3];
  435. if (size == 1 || size == 2) {
  436. chars[0] = '*';
  437. chars[1] = ' ';
  438. chars[2] = name[size - 1];
  439. } else {
  440. chars[0] = '*';
  441. chars[1] = name[size - 2];
  442. chars[2] = name[size - 1];
  443. }
  444. return new String(chars);
  445. }
  446. public static String getRealAddressByIP(String ip) {
  447. if (StrUtil.isBlank(ip)) {
  448. return "unknown";
  449. }
  450. try {
  451. String url = String.format("http://whois.pconline.com.cn/ipJson.jsp?ip=%s" + "&json=true", ip);
  452. HttpResponse<String> send = J11HttpC
  453. .custom().ofGet().url(url)
  454. .send(HttpResponse.BodyHandlers.ofString());
  455. String rspStr = send.body();
  456. if (StrUtil.isEmpty(rspStr)) {
  457. return "unknown";
  458. }
  459. JSONObject obj = JSONUtil.parseObj(rspStr);
  460. String region = obj.getStr("pro");
  461. String city = obj.getStr("city");
  462. return String.format("%s %s", region, city);
  463. } catch (Exception e) {
  464. }
  465. return "unknown";
  466. }
  467. public static String getInternalAddressByIP(String ip) {
  468. if (StrUtil.isBlank(ip)) {
  469. return "unknown";
  470. }
  471. try {
  472. String url = String.format("http://whois.pconline.com.cn/ipJson.jsp?ip=%s" + "&json=true", ip);
  473. HttpResponse<String> send = J11HttpC
  474. .custom().ofGet().url(url)
  475. .send(HttpResponse.BodyHandlers.ofString());
  476. String rspStr = send.body();
  477. if (StrUtil.isEmpty(rspStr)) {
  478. return "unknown";
  479. }
  480. JSONObject obj = JSONUtil.parseObj(rspStr);
  481. String addr = obj.getStr("addr");
  482. return addr;
  483. } catch (Exception e) {
  484. }
  485. return "unknown";
  486. }
  487. /**
  488. * 付费ip地址查询
  489. */
  490. public static String getNewestIpAddress(String ip) {
  491. cn.hutool.http.HttpResponse execute = HttpUtil.createGet(String.format("https://ipaddr.market.alicloudapi.com/ip_addr_search/v1?IP_ADDR=%s", ip))
  492. .header("Authorization", PAID_IP_APP_CODE_AUTH)
  493. .header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
  494. .execute();
  495. try {
  496. ArkIpAddressDto arkIpAddressDto = Jsons.parseObject(execute.body(), ArkIpAddressDto.class);
  497. ArkIpAddressDto.Entity.InputIpAddress inputIpAddress = arkIpAddressDto.getEntity().getInputIpAddress();
  498. return inputIpAddress.getCity();
  499. } catch (Exception e) {
  500. }
  501. return "unknown";
  502. }
  503. /**
  504. * 身份证号返回
  505. */
  506. public static String enIndent(String ident) {
  507. String front = ident.substring(0, 4);
  508. String back = ident.substring(ident.length() - 4);
  509. StringBuilder sb = new StringBuilder();
  510. sb.append(front).append("****").append(back);
  511. return sb.toString();
  512. }
  513. public static String getNewInternalAddressByIp(String ip) {
  514. if (StrUtil.isBlank(ip)) {
  515. return "unknown";
  516. }
  517. try {
  518. String url = String.format("https://searchplugin.csdn.net/api/v1/ip/get?ip=%s", ip);
  519. HttpResponse<String> send = J11HttpC
  520. .custom().ofGet().url(url)
  521. .send(HttpResponse.BodyHandlers.ofString());
  522. String rspStr = send.body();
  523. if (StrUtil.isEmpty(rspStr)) {
  524. return "unknown";
  525. }
  526. JSONObject obj = JSONUtil.parseObj(rspStr);
  527. JSONObject data = JSONUtil.parseObj(obj.get("data"));
  528. String addr = data.getStr("address");
  529. return addr;
  530. } catch (Exception e) {
  531. }
  532. return "unknown";
  533. }
  534. /**
  535. * 获取账号登录验证码
  536. */
  537. public static String getVerifyCodePattern(String code, Integer length) {
  538. if (StrUtil.isNotEmpty(code)) {
  539. Pattern pattern = Pattern.compile(String.format("\\d{%s,}", length));
  540. Matcher matcher = pattern.matcher(code);
  541. while (matcher.find()) {
  542. return matcher.group();
  543. }
  544. }
  545. return StrUtil.EMPTY;
  546. }
  547. public static <T> List<List<T>> averageAssign(List<T> source, int n) {
  548. List<List<T>> result = new ArrayList<List<T>>();
  549. int remainder = source.size() % n; //(先计算出余数)
  550. int number = source.size() / n; //然后是商
  551. int offset = 0;//偏移量
  552. for (int i = 0; i < n; i++) {
  553. List<T> value = null;
  554. if (remainder > 0) {
  555. value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
  556. remainder--;
  557. offset++;
  558. } else {
  559. value = source.subList(i * number + offset, (i + 1) * number + offset);
  560. }
  561. result.add(value);
  562. }
  563. return result;
  564. }
  565. /**
  566. * 付费ip地址查询
  567. */
  568. public static String paidIpAddress(String ip) {
  569. cn.hutool.http.HttpResponse execute = HttpUtil.createGet(String.format("https://ipaddr.market.alicloudapi.com/ip_addr_search/v1?IP_ADDR=%s", ip))
  570. .header("Authorization", PAID_IP_APP_CODE_AUTH)
  571. .header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
  572. .execute();
  573. try {
  574. ArkIpAddressDto arkIpAddressDto = Jsons.parseObject(execute.body(), ArkIpAddressDto.class);
  575. ArkIpAddressDto.Entity.InputIpAddress inputIpAddress = arkIpAddressDto.getEntity().getInputIpAddress();
  576. return new StringBuilder()
  577. .append(inputIpAddress.getNation())
  578. .append(inputIpAddress.getProvince())
  579. .append(inputIpAddress.getCity()).toString();
  580. } catch (Exception e) {
  581. }
  582. return "unknown";
  583. }
  584. /**
  585. * 姓名返回
  586. */
  587. public static String enName(String name) {
  588. String first = name.substring(0, 1);
  589. if (name.length() <= 2) {
  590. return first + "*";
  591. }
  592. String end = name.substring(name.length() - 1);
  593. StringBuilder sb = new StringBuilder();
  594. sb.append(first).append("*").append(end);
  595. return sb.toString();
  596. }
  597. }