StringUtil.java 15 KB

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