Files
timi-io/src/main/java/com/imyeyu/io/IOSize.java
2025-10-24 11:58:46 +08:00

229 lines
5.3 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.imyeyu.io;
import com.imyeyu.java.TimiJava;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 字节大小工具
*
* @author 夜雨
* @version 2023-06-01 16:41
*/
public class IOSize {
/**
* 储存单位
*
* @author 夜雨
* @version 2022-04-08 14:37
*/
public enum Unit {
/** B */
B,
/** KB */
KB,
/** MB */
MB,
/** GB */
GB,
/** TB */
TB,
/** PB */
PB,
/** EB */
EB;
/**
* 转换字节量
*
* @param value 值
* @return 该单位值字节量
*/
public long toBytes(double value) {
return (long) (value * Math.pow(1024, ordinal()));
}
}
/** 1 字节 */
public static long BYTE = 1;
/** 1 KB */
public static long KB = BYTE << 10;
/** 1 MB */
public static long MB = KB << 10;
/** 1 GB */
public static long GB = MB << 10;
/** 1 TB */
public static long TB = GB << 10;
/** 1 PB */
public static long PB = TB << 10;
/** 1 EB */
public static long EB = PB << 10;
/**
* <p>格式化一个储存容量,保留两位小数
* <pre>
* // 返回 100.01 KB
* Tools.byteFormat(102411, 2);
* </pre>
*
* @param size 字节大小
* @return 格式化结果
*/
public static String format(double size) {
return format(size, 2, null);
}
/**
* <p>格式化一个储存容量
* <pre>
* // 返回 100.01 KB
* Tools.byteFormat(102411, 2);
* </pre>
*
* @param size 字节大小
* @param stopUnit 最高等级,格式化到某单位后不再升级,最低 {@link Unit#B},最高 {@link Unit#EB}
* @return 格式化结果
*/
public static String format(double size, Unit stopUnit) {
return format(size, 2, stopUnit);
}
/**
* <p>格式化一个储存容量
* <pre>
* // 返回 100.01 KB
* Tools.byteFormat(102411, 2);
* </pre>
*
* @param size 字节大小
* @param decimal 保留小数
* @param stopUnit 最高等级,格式化到某单位后不再升级,最低 {@link Unit#B},最高 {@link Unit#EB}
* @return 格式化结果
*/
public static String format(double size, int decimal, Unit stopUnit) {
final Unit[] unit = Unit.values();
if (0 < size) {
for (int i = 0; i < unit.length; i++, size /= 1024d) {
if (size <= 1000 || i == unit.length - 1 || unit[i] == stopUnit) {
if (i == 0) {
// 最小单位不需要小数
return (int) size + " B";
} else {
String format = "%." + decimal + "f " + unit[i];
return String.format(format, size);
}
}
}
}
return "0 B";
}
/**
* <p>格式化一个储存容量,不带单位
* <pre>
* // 返回 100.01
* Tools.byteFormat(102411, 2);
* </pre>
*
* @param size 字节大小
* @param decimal 保留小数
* @param stopUnit 最高等级,格式化到某单位后不再升级,最低 {@link Unit#B},最高 {@link Unit#TB}
* @return 格式化结果(不带单位)
*/
public static String formatWithoutUnit(double size, int decimal, Unit stopUnit) {
final Unit[] unit = Unit.values();
if (0 < size) {
for (int i = 0; i < unit.length; i++, size /= 1024d) {
if (size <= 1000 || i == unit.length - 1 || unit[i] == stopUnit) {
if (i == 0) {
return String.valueOf((int) size);
} else {
String format = "%." + decimal + "f";
return String.format(format, size);
}
}
}
}
return "0";
}
/**
* 将格式化的储存量字符串解析为字节量
* <p>支持格式10GB, 10 GB, 1TB, 1.24 KB 等(单位不区分大小写)</p>
* <pre>
* // 返回 102400
* IOSize.parse("100 KB");
* // 返回 1073741824
* IOSize.parse("1GB");
* </pre>
*
* @param sizeStr 格式化后的储存量字符串
* @return 字节量
* @throws IllegalArgumentException 格式无效
*/
public static long parse(String sizeStr) {
if (TimiJava.isEmpty(sizeStr)) {
throw new IllegalArgumentException("not found sizeStr");
}
// 正则匹配:可选符号 + 数字(含小数点)+ 可选空格 + 单位
Pattern pattern = Pattern.compile("([-+]?\\d+(?:\\.\\d+)?)\\s*([a-zA-Z]+)");
Matcher matcher = pattern.matcher(sizeStr.trim());
if (matcher.find()) {
double value;
try {
value = Double.parseDouble(matcher.group(1));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("invalid number format: " + matcher.group(1), e);
}
if (value < 0) {
throw new IllegalArgumentException("size cannot be negative: " + value);
}
String unitStr = matcher.group(2).toUpperCase();
Unit unit;
try {
unit = Unit.valueOf(unitStr);
} catch (IllegalArgumentException e) {
// 处理单字母单位缩写K/M/G/T/P/E
unit = switch (unitStr.charAt(0)) {
case 'K' -> Unit.KB;
case 'M' -> Unit.MB;
case 'G' -> Unit.GB;
case 'T' -> Unit.TB;
case 'P' -> Unit.PB;
case 'E' -> Unit.EB;
case 'B' -> Unit.B;
default -> throw new IllegalArgumentException("Unknown unit: " + unitStr);
};
}
return unit.toBytes(value);
}
// 尝试解析纯数字(无单位,默认字节)
try {
long bytes = Long.parseLong(sizeStr.trim());
if (bytes < 0) {
throw new IllegalArgumentException("size cannot be negative: " + bytes);
}
return bytes;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("invalid size format: " + sizeStr, e);
}
}
}