Initial project
This commit is contained in:
463
src/main/java/com/imyeyu/utils/Text.java
Normal file
463
src/main/java/com/imyeyu/utils/Text.java
Normal file
@ -0,0 +1,463 @@
|
||||
package com.imyeyu.utils;
|
||||
|
||||
import com.imyeyu.java.TimiJava;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @version 2023-08-07 11:58
|
||||
*/
|
||||
public class Text {
|
||||
|
||||
/** 十六进制小写 */
|
||||
public static char[] HEX_DIGITS_LOWER = "0123456789abcdef".toCharArray();
|
||||
|
||||
/** 十六进制大写 */
|
||||
public static char[] HEX_DIGITS_UPPER = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
/**
|
||||
* 字节数据转 16 进制字符串
|
||||
*
|
||||
* @param bytes 字节数据
|
||||
* @return 16 进制字符串
|
||||
*/
|
||||
public static String byteToHex(byte[] bytes) {
|
||||
final int l = bytes.length;
|
||||
final char[] c = new char[l << 1];
|
||||
for (int i = 0, j = 0; i < l; i++) {
|
||||
c[j++] = Text.HEX_DIGITS_LOWER[(0xF0 & bytes[i]) >>> 4];
|
||||
c[j++] = Text.HEX_DIGITS_LOWER[0x0F & bytes[i]];
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 16 进制字符串转字节数据
|
||||
*
|
||||
* @param hex 16 进制字符串
|
||||
* @return 字节数据
|
||||
* @throws UnsupportedEncodingException 不支持的编码
|
||||
*/
|
||||
public static byte[] hexToByte(String hex) throws UnsupportedEncodingException {
|
||||
final char[] c = hex.toCharArray();
|
||||
final byte[] b = new byte[c.length >> 1];
|
||||
|
||||
final int len = c.length;
|
||||
if ((len & 0x01) != 0) {
|
||||
throw new UnsupportedEncodingException("Odd number of characters.");
|
||||
}
|
||||
|
||||
final int outLen = len >> 1;
|
||||
if (c.length < outLen) {
|
||||
throw new UnsupportedEncodingException("Output array is not large enough to accommodate decoded data.");
|
||||
}
|
||||
for (int i = 0, j = 0; j < len; i++) {
|
||||
int f = toDigit(c[j], j) << 4;
|
||||
j++;
|
||||
f = f | toDigit(c[j], j);
|
||||
j++;
|
||||
b[i] = (byte) (f & 0xFF);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private static int toDigit(final char ch, final int index) throws UnsupportedEncodingException {
|
||||
final int digit = Character.digit(ch, 16);
|
||||
if (digit == -1) {
|
||||
throw new UnsupportedEncodingException("Illegal hexadecimal character " + ch + " at index " + index);
|
||||
}
|
||||
return digit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为半角字符
|
||||
*
|
||||
* @param c 字符
|
||||
* @return 为 true 是表示是半角字符
|
||||
*/
|
||||
public static boolean isHalfChar(char c) {
|
||||
return (int) c < 129;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串加双引号
|
||||
*
|
||||
* @param text 字符串内容
|
||||
* @return 结果
|
||||
*/
|
||||
public static String quote(String text) {
|
||||
return '"' + text + '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* 前补零(最终长度 2 字符)
|
||||
*
|
||||
* @param number 数值
|
||||
* @return 补零字符串
|
||||
*/
|
||||
public static String zero(Number number) {
|
||||
return zero(2, number);
|
||||
}
|
||||
|
||||
public static String paddedSpaceStart(String str, int totalWidth) {
|
||||
return String.format("%" + totalWidth + "s", str);
|
||||
}
|
||||
|
||||
public static String paddedSpaceEnd(String str, int totalWidth) {
|
||||
return String.format("%-" + totalWidth + "s", str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 前补零
|
||||
*
|
||||
* @param l 最终长度
|
||||
* @param number 数值
|
||||
* @return 补零字符串
|
||||
*/
|
||||
public static String zero(int l, Number number) {
|
||||
return String.format("%0" + l + "d", number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 正则表达式测试
|
||||
*
|
||||
* @param reg 正则
|
||||
* @param value 文本
|
||||
* @return true 为匹配
|
||||
*/
|
||||
public static boolean testReg(String reg, String value) {
|
||||
return Pattern.compile(reg).matcher(value).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线
|
||||
*
|
||||
* @param camelCaseStr 驼峰字符串
|
||||
* @return 下划线字符串
|
||||
*/
|
||||
public static String camelCase2underscore(String camelCaseStr) {
|
||||
return camelCaseStr.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线转驼峰
|
||||
*
|
||||
* @param underscoreName 下划线字符串
|
||||
* @return 驼峰字符串
|
||||
*/
|
||||
public static String underscore2camelCase(String underscoreName) {
|
||||
if (TimiJava.isEmpty(underscoreName)) {
|
||||
return underscoreName;
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean flag = false;
|
||||
for (int i = 0; i < underscoreName.length(); i++) {
|
||||
char c = underscoreName.charAt(i);
|
||||
if ('_' == c) {
|
||||
flag = true;
|
||||
} else {
|
||||
if (flag) {
|
||||
result.append(Character.toUpperCase(c));
|
||||
flag = false;
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 与多个字符串进行与比较
|
||||
*
|
||||
* @param string 比较字符串
|
||||
* @param other 其他字符串
|
||||
* @return true 时全部其他字符串和比较字符串一致
|
||||
*/
|
||||
public static boolean eqAnd(String string, String... other) {
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
if (!string.equals(other[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与多个字符串进行或比较
|
||||
*
|
||||
* @param string 比较字符串
|
||||
* @param other 其他字符串
|
||||
* @return true 时其他字符串存在和比较字符串一致
|
||||
*/
|
||||
public static boolean eqOr(String string, String... other) {
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
if (!string.equals(other[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与多个字符串进行忽略大小写的与比较
|
||||
*
|
||||
* @param string 比较字符串
|
||||
* @param other 其他字符串
|
||||
* @return true 时全部其他字符串和比较字符串一致
|
||||
*/
|
||||
public static boolean eqIgnoreCaseAnd(String string, String... other) {
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
if (!string.equalsIgnoreCase(other[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与多个字符串进行忽略大小写的或比较
|
||||
*
|
||||
* @param string 比较字符串
|
||||
* @param other 其他字符串
|
||||
* @return true 时其他字符串存在和比较字符串一致
|
||||
*/
|
||||
public static boolean eqIgnoreCaseOr(String string, String... other) {
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
if (string.equalsIgnoreCase(other[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与多个字符串进行忽略大小写包含关系
|
||||
*
|
||||
* @param string 原字符串
|
||||
* @param other 其他字符串
|
||||
* @return true 为 string 中至少含有一个 other 的忽略大小写的字符段
|
||||
*/
|
||||
public static boolean containsIgnoreCase(String string, String... other) {
|
||||
String stringUpper = string.toUpperCase();
|
||||
String stringLower = string.toLowerCase();
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
if (stringLower.contains(other[i].toLowerCase()) || stringUpper.contains(other[i].toUpperCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String randomString(int length) {
|
||||
return randomString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", length);
|
||||
}
|
||||
|
||||
public static String randomString(String pool, int length) {
|
||||
SecureRandom r = new SecureRandom();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(pool.charAt(r.nextInt(pool.length() - 1)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 较短的临时 UUID,如果使用在庞大的数据里,很可能会发生重复
|
||||
*
|
||||
* @return 完整 UUID 前 8 位
|
||||
*/
|
||||
public static String tempUUID() {
|
||||
return UUID.randomUUID().toString().substring(0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算字符串相似度(编辑距离算法)
|
||||
*
|
||||
* @param source 需比较的字符串
|
||||
* @param target 被比较的字符串
|
||||
* @param isIgnore 为 true 时忽略大小写
|
||||
* @return 相似度 [0, 1]
|
||||
*/
|
||||
private static float levenshteinDistance(String source, String target, boolean isIgnore) {
|
||||
int[][] d;
|
||||
int n = source.length(), m = target.length(), i, j, temp;
|
||||
char charS, charT;
|
||||
|
||||
if (n == 0) {
|
||||
return m;
|
||||
}
|
||||
if (m == 0) {
|
||||
return n;
|
||||
}
|
||||
|
||||
d = new int[n + 1][m + 1];
|
||||
for (i = 0; i <= n; i++) {
|
||||
d[i][0] = i;
|
||||
}
|
||||
for (j = 0; j <= m; j++) {
|
||||
d[0][j] = j;
|
||||
}
|
||||
for (i = 1; i <= n; i++) {
|
||||
charS = source.charAt(i - 1);
|
||||
for (j = 1; j <= m; j++) {
|
||||
charT = target.charAt(j - 1);
|
||||
if (isIgnore) {
|
||||
if (charS == charT || charS == charT + 32 || charS + 32 == charT) {
|
||||
temp = 0;
|
||||
} else {
|
||||
temp = 1;
|
||||
}
|
||||
} else {
|
||||
if (charS == charT) {
|
||||
temp = 0;
|
||||
} else {
|
||||
temp = 1;
|
||||
}
|
||||
}
|
||||
d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
|
||||
}
|
||||
}
|
||||
return d[n][m];
|
||||
}
|
||||
|
||||
/**
|
||||
* 三数求最小
|
||||
*
|
||||
* @param one 值一
|
||||
* @param two 值二
|
||||
* @param three 值三
|
||||
* @return 最小值
|
||||
*/
|
||||
public static int min(int one, int two, int three) {
|
||||
return (one = Math.min(one, two)) < three ? one : three;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量相似度比较字符串(忽略大小写),返回相似度比较列表倒叙结果,较为相似的排最前
|
||||
*
|
||||
* @param sources 需比较的字符串列表
|
||||
* @param target 被比较的字符串
|
||||
* @return 比较结果列表
|
||||
*/
|
||||
public static LinkedHashMap<String, Number> similarityRatioList(Collection<String> sources, String target) {
|
||||
return similarityRatioList(sources, target, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量相似度比较字符串,返回相似度比较列表倒叙结果,较为相似的排最前
|
||||
*
|
||||
* @param sources 需比较的字符串列表
|
||||
* @param target 被比较的字符串
|
||||
* @param isIgnoreCase true 为忽略大小写
|
||||
* @return 比较结果列表
|
||||
*/
|
||||
public static LinkedHashMap<String, Number> similarityRatioList(Collection<String> sources, String target, boolean isIgnoreCase) {
|
||||
Map<String, Number> items = new HashMap<>();
|
||||
for (String source : sources) {
|
||||
items.put(source, 0);
|
||||
}
|
||||
items.replaceAll((k, v) -> similarityRatio(k, target, isIgnoreCase));
|
||||
return Collect.sortMapByNumberValueDESC(items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 求字符串相似度,忽略大小写
|
||||
*
|
||||
* @param source 需比较的字符串
|
||||
* @param target 被比较的字符串
|
||||
* @return 相似度 [0, 1]
|
||||
*/
|
||||
public static float similarityRatio(String source, String target) {
|
||||
return similarityRatio(source, target, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 求字符串相似度
|
||||
*
|
||||
* @param source 需比较的字符串
|
||||
* @param target 被比较的字符串
|
||||
* @param isIgnoreCase true 为忽略大小写
|
||||
* @return 相似度 [0, 1]
|
||||
*/
|
||||
public static float similarityRatio(String source, String target, boolean isIgnoreCase) {
|
||||
float ret;
|
||||
final int max = Math.max(source.length(), target.length());
|
||||
if (max == 0) {
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 1 - levenshteinDistance(source, target, isIgnoreCase) / max;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验字符串是否为 json 数据,不校验是否有错误
|
||||
*
|
||||
* @param s 字符串
|
||||
* @return true 为是 JSON 数据
|
||||
*/
|
||||
public static boolean isJson(String s) {
|
||||
return isJsonObject(s) || isJsonArray(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验字符串是否为 json 对象,不校验是否有错误
|
||||
*
|
||||
* @param s 字符串
|
||||
* @return true 为是 JSON 对象
|
||||
*/
|
||||
public static boolean isJsonObject(String s) {
|
||||
return s.startsWith("{") && s.endsWith("}");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检验字符串是否为 json 数组,不校验是否有错误
|
||||
*
|
||||
* @param s 字符串
|
||||
* @return true 为是 JSON 数组
|
||||
*/
|
||||
public static boolean isJsonArray(String s) {
|
||||
return s.startsWith("[") && s.endsWith("]");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 字符串替换,不需要正则的情况下
|
||||
*
|
||||
* @param string 字符串
|
||||
* @param from 被替换字符
|
||||
* @param to 替换字符串
|
||||
* @return 替换结果
|
||||
*/
|
||||
public static String replaceAll(String string, char from, String to) {
|
||||
return replaceAll(new StringBuilder(string), from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串替换,不需要正则的情况下
|
||||
*
|
||||
* @param sb 字符构造器
|
||||
* @param from 被替换字符
|
||||
* @param to 替换字符串
|
||||
* @return 替换结果
|
||||
*/
|
||||
public static String replaceAll(StringBuilder sb, char from, String to) {
|
||||
for (int i = 0; i < sb.length(); i++) {
|
||||
if (sb.charAt(i) == from) {
|
||||
sb.replace(i, ++i, to);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user