Dock-MultiCtrl/admin/src/main/java/com/multictrl/common/utils/Utils.java

283 lines
8.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.multictrl.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.NameFilter;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.imaging.mp4.Mp4MetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.multictrl.common.exception.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* 通用工具
*
* @author Sdy
* @since 1.0.0 2026/4/24
*/
@Slf4j
public class Utils {
/**
* 线程休息n毫秒
*/
public static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
log.error("线程睡眠异常:{}", ExceptionUtils.getErrorStackTrace(e));
}
}
/*
* 驼峰转下划线
*/
public static JSONObject beanToSnakeJson(Object obj) {
JSONObject camelJson = JSONUtil.parseObj(obj);
JSONObject snakeJson = new JSONObject();
for (String key : camelJson.keySet()) {
String snakeKey = StrUtil.toUnderlineCase(key); // 驼峰转下划线
Object value = camelJson.get(key);
// 递归处理嵌套 JSONObject 或 JSONArray
if (value instanceof JSONObject) {
value = beanToSnakeJson(value); // 递归转换
} else if (value instanceof JSONArray) {
JSONArray arr = new JSONArray();
for (Object item : (JSONArray) value) {
if (item instanceof JSONObject) {
arr.add(beanToSnakeJson(item));
} else {
arr.add(item);
}
}
value = arr;
}
snakeJson.set(snakeKey, value);
}
return snakeJson;
}
/*
* 阿里FastJson2驼峰转下划线
*/
public static com.alibaba.fastjson2.JSONObject beanToSnakeJsonFastJson(Object o) {
NameFilter snakeCaseFilter = (object, name, value)
-> name.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
return com.alibaba.fastjson2.JSONObject.parseObject(JSON.toJSONString(o, snakeCaseFilter));
}
/**
* 获取最后两个字符
* "a/b/c/d" "c/d"
*/
public static String getLastTwoSegments(String str, String separator) {
if (StrUtil.isBlank(str)) return str;
// 按分隔符切割
List<String> parts = StrUtil.split(str, separator);
if (parts.size() <= 2) {
return str; // 不足两段则原样返回
} else {
// 取最后两段
List<String> lastTwo = parts.subList(parts.size() - 2, parts.size());
return CollUtil.join(lastTwo, String.valueOf(separator));
}
}
/**
* 文件转md5
*/
public static String md5File(String path) {
StringBuilder sb = new StringBuilder();
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(FileUtils.readFileToByteArray(new File(path)));
byte[] b = md.digest();
int d;
for (byte value : b) {
d = value;
if (d < 0) {
d = value & 0xff;
// 与上一行效果等同
// i += 256;
}
if (d < 16) {
sb.append("0");
}
sb.append(Integer.toHexString(d));
}
} catch (NoSuchAlgorithmException | IOException e) {
log.error("md5 fail", e);
}
return sb.toString();
}
/**
* 获取文本的md5
*/
public static String md5Txt(String context) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] buffer = context.getBytes();
md.update(buffer, 0, buffer.length);
byte[] digest = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException exception) {
log.error("md5 fail", exception);
}
return null;
}
/**
* 获取图片的Windows XP Keywords
*/
public static String getImageWindowsXpKeywords(String mediaPath) {
Metadata metadata;
try {
metadata = JpegMetadataReader.readMetadata(new File(mediaPath));
for (Directory exif : metadata.getDirectories()) {
for (Tag tag : exif.getTags()) {
if ("Windows XP Keywords".equals(tag.getTagName())) {
return tag.getDescription();
}
}
}
} catch (JpegProcessingException | IOException e) {
log.error("error", e);
}
return null;
}
public static long getImageTime(String mediaPath) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
Metadata metadata;
try {
metadata = JpegMetadataReader.readMetadata(new File(mediaPath));
for (Directory exif : metadata.getDirectories()) {
for (Tag tag : exif.getTags()) {
if ("Date/Time".equals(tag.getTagName())) {
return sdf.parse(tag.getDescription()).getTime();
}
}
}
} catch (JpegProcessingException | IOException e) {
log.error("error", e);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return 0;
}
public static long getVideoTime(String videoPath) {
Metadata metadata;
try {
metadata = Mp4MetadataReader.readMetadata(new File(videoPath));
for (Directory exif : metadata.getDirectories()) {
for (Tag tag : exif.getTags()) {
if ("Creation Time".equals(tag.getTagName())) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",
Locale.US);
Date d = sdf.parse(tag.getDescription());
return d.getTime();
} catch (ParseException ignored) {
}
}
}
}
} catch (IOException e) {
log.error("error", e);
}
return 0;
}
/**
* 格式化double保留指定位小数四舍五入
*
* @param value 原始数值
* @param scale 小数位数
* @return 格式化后的字符串
*/
private static String format(double value, int scale) {
if (Double.isNaN(value) || Double.isInfinite(value)) {
return "0";
}
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(scale, RoundingMode.HALF_UP);
return bd.stripTrailingZeros().toPlainString();
}
/**
* 字节数格式化为人性化字符串自动选择B, KB, MB, GB, TB
* 1024进制
*
* @param bytes 字节数
* @return 如 "1.45 GB"
*/
public static String formatBytes(long bytes) {
if (bytes < 0) {
return "0 B";
}
if (bytes < 1024) {
return bytes + " B";
}
int exp = (int) (Math.log(bytes) / Math.log(1024));
char pre = "KMGTPE".charAt(exp - 1);
double result = bytes / Math.pow(1024, exp);
return format(result, 2) + " " + pre + "B";
}
/**
* 将秒转换为分秒
*/
public static String calculateSeconds(long totalSeconds) {
// 处理负数
if (totalSeconds < 0) {
return "-" + calculateSeconds(-totalSeconds);
}
long hours = totalSeconds / 3600;
long minutes = (totalSeconds % 3600) / 60;
long seconds = totalSeconds % 60;
StringBuilder sb = new StringBuilder();
if (hours > 0) {
sb.append(hours).append('h');
}
if (minutes > 0) {
sb.append(minutes).append('m');
}
// 当所有部分都为0时至少显示 "0s"
if (seconds > 0 || sb.isEmpty()) {
sb.append(seconds).append('s');
}
return sb.toString();
}
}