229 lines
5.3 KiB
Java
229 lines
5.3 KiB
Java
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);
|
||
}
|
||
}
|
||
}
|