StringUtil.java 13 KB

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