如何在Java中将字节大小转换为人类可读的格式?
比如1024应该变成“1 Kb”,1024*1024应该变成“1 Mb”。
我有点厌倦了为每个项目写这个实用方法。在Apache Commons中有这样的静态方法吗?
如何在Java中将字节大小转换为人类可读的格式?
比如1024应该变成“1 Kb”,1024*1024应该变成“1 Mb”。
我有点厌倦了为每个项目写这个实用方法。在Apache Commons中有这样的静态方法吗?
当前回答
现在有一个包含单元格式的库可用。我把它添加到triava库,因为唯一的其他现有库似乎是Android的。
它可以格式化数字与任意精度,在3个不同的系统(SI, IEC, JEDEC)和各种输出选项。下面是来自triava单元测试的一些代码示例:
UnitFormatter.formatAsUnit(1126, UnitSystem.SI, "B");
// = "1.13kB"
UnitFormatter.formatAsUnit(2094, UnitSystem.IEC, "B");
// = "2.04KiB"
打印精确的千克,百万值(这里用W =瓦特):
UnitFormatter.formatAsUnits(12_000_678, UnitSystem.SI, "W", ", ");
// = "12MW, 678W"
你可以传递一个DecimalFormat来定制输出:
UnitFormatter.formatAsUnit(2085, UnitSystem.IEC, "B", new DecimalFormat("0.0000"));
// = "2.0361KiB"
对于kilo或mega值的任意操作,您可以将它们拆分为组件:
UnitComponent uc = new UnitComponent(123_345_567_789L, UnitSystem.SI);
int kilos = uc.kilo(); // 567
int gigas = uc.giga(); // 123
其他回答
这是aioobe答案的修改版本。
变化:
Locale参数,因为有些语言使用。其他的,作为小数点。 人类可读的代码
private static final String[] SI_UNITS = { "B", "kB", "MB", "GB", "TB", "PB", "EB" };
private static final String[] BINARY_UNITS = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" };
public static String humanReadableByteCount(final long bytes, final boolean useSIUnits, final Locale locale)
{
final String[] units = useSIUnits ? SI_UNITS : BINARY_UNITS;
final int base = useSIUnits ? 1000 : 1024;
// When using the smallest unit no decimal point is needed, because it's the exact number.
if (bytes < base) {
return bytes + " " + units[0];
}
final int exponent = (int) (Math.log(bytes) / Math.log(base));
final String unit = units[exponent];
return String.format(locale, "%.1f %s", bytes / Math.pow(base, exponent), unit);
}
创建接口:
public interface IUnits {
public String format(long size, String pattern);
public long getUnitSize();
}
创建StorageUnits类:
import java.text.DecimalFormat;
public class StorageUnits {
private static final long K = 1024;
private static final long M = K * K;
private static final long G = M * K;
private static final long T = G * K;
enum Unit implements IUnits {
TERA_BYTE {
@Override
public String format(long size, String pattern) {
return format(size, getUnitSize(), "TB", pattern);
}
@Override
public long getUnitSize() {
return T;
}
@Override
public String toString() {
return "Terabytes";
}
},
GIGA_BYTE {
@Override
public String format(long size, String pattern) {
return format(size, getUnitSize(), "GB", pattern);
}
@Override
public long getUnitSize() {
return G;
}
@Override
public String toString() {
return "Gigabytes";
}
},
MEGA_BYTE {
@Override
public String format(long size, String pattern) {
return format(size, getUnitSize(), "MB", pattern);
}
@Override
public long getUnitSize() {
return M;
}
@Override
public String toString() {
return "Megabytes";
}
},
KILO_BYTE {
@Override
public String format(long size, String pattern) {
return format(size, getUnitSize(), "kB", pattern);
}
@Override
public long getUnitSize() {
return K;
}
@Override
public String toString() {
return "Kilobytes";
}
};
String format(long size, long base, String unit, String pattern) {
return new DecimalFormat(pattern).format(
Long.valueOf(size).doubleValue() /
Long.valueOf(base).doubleValue()
) + unit;
}
}
public static String format(long size, String pattern) {
for(Unit unit : Unit.values()) {
if(size >= unit.getUnitSize()) {
return unit.format(size, pattern);
}
}
return ("???(" + size + ")???");
}
public static String format(long size) {
return format(size, "#,##0.#");
}
}
叫它:
class Main {
public static void main(String... args) {
System.out.println(StorageUnits.format(21885));
System.out.println(StorageUnits.format(2188121545L));
}
}
输出:
21.4kB
2GB
试试JSR 363。它的单元扩展模块,如Unicode CLDR(在GitHub: uom-systems中),为您完成所有这些。
你可以使用每个实现中包含的MetricPrefix或BinaryPrefix(与上面的一些例子相比),如果你在印度或附近的国家生活和工作,IndianPrefix(也在uom-系统的公共模块中)允许你使用和格式化“千万字节”或“Lakh字节”。
String[] fileSizeUnits = {"bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
public String calculateProperFileSize(double bytes){
String sizeToReturn = "";
int index = 0;
for(index = 0; index < fileSizeUnits.length; index++){
if(bytes < 1024){
break;
}
bytes = bytes / 1024;
}
System.out.println("File size in proper format: " + bytes + " " + fileSizeUnits[index]);
sizeToReturn = String.valueOf(bytes) + " " + fileSizeUnits[index];
return sizeToReturn;
}
只需添加更多的文件单元(如果有任何缺失),你将看到单元大小达到该单元(如果你的文件有那么长):
下面是一个快速,简单和可读的代码片段来实现这一点:
/**
* Converts byte size to human readable strings (also declares useful constants)
*
* @see <a href="https://en.wikipedia.org/wiki/File_size">File size</a>
*/
@SuppressWarnings("SpellCheckingInspection")
public class HumanReadableSize {
public static final double
KILO = 1000L, // 1000 power 1 (10 power 3)
KIBI = 1024L, // 1024 power 1 (2 power 10)
MEGA = KILO * KILO, // 1000 power 2 (10 power 6)
MEBI = KIBI * KIBI, // 1024 power 2 (2 power 20)
GIGA = MEGA * KILO, // 1000 power 3 (10 power 9)
GIBI = MEBI * KIBI, // 1024 power 3 (2 power 30)
TERA = GIGA * KILO, // 1000 power 4 (10 power 12)
TEBI = GIBI * KIBI, // 1024 power 4 (2 power 40)
PETA = TERA * KILO, // 1000 power 5 (10 power 15)
PEBI = TEBI * KIBI, // 1024 power 5 (2 power 50)
EXA = PETA * KILO, // 1000 power 6 (10 power 18)
EXBI = PEBI * KIBI; // 1024 power 6 (2 power 60)
private static final DecimalFormat df = new DecimalFormat("#.##");
public static String binaryBased(long size) {
if (size < 0) {
throw new IllegalArgumentException("Argument cannot be negative");
} else if (size < KIBI) {
return df.format(size).concat("B");
} else if (size < MEBI) {
return df.format(size / KIBI).concat("KiB");
} else if (size < GIBI) {
return df.format(size / MEBI).concat("MiB");
} else if (size < TEBI) {
return df.format(size / GIBI).concat("GiB");
} else if (size < PEBI) {
return df.format(size / TEBI).concat("TiB");
} else if (size < EXBI) {
return df.format(size / PEBI).concat("PiB");
} else {
return df.format(size / EXBI).concat("EiB");
}
}
public static String decimalBased(long size) {
if (size < 0) {
throw new IllegalArgumentException("Argument cannot be negative");
} else if (size < KILO) {
return df.format(size).concat("B");
} else if (size < MEGA) {
return df.format(size / KILO).concat("KB");
} else if (size < GIGA) {
return df.format(size / MEGA).concat("MB");
} else if (size < TERA) {
return df.format(size / GIGA).concat("GB");
} else if (size < PETA) {
return df.format(size / TERA).concat("TB");
} else if (size < EXA) {
return df.format(size / PETA).concat("PB");
} else {
return df.format(size / EXA).concat("EB");
}
}
}
注意:
上面的代码冗长而简单。 它不使用循环(循环应该只在您不知道在编译期间需要迭代多少次时使用) 它不会进行不必要的库调用(StringBuilder, Math等) 上面的代码是快速的,使用非常少的内存。基于在我个人的入门级云计算机上运行的基准测试,它是最快的(在这些情况下性能并不重要,但仍然如此) 以上代码是一个很好的答案的修改版本