Initial project

This commit is contained in:
Timi
2025-07-12 12:45:46 +08:00
parent a87693cf37
commit abf09cee04
20 changed files with 2769 additions and 94 deletions

View 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();
}
}