如何在Java中将字节大小转换为人类可读的格式?

比如1024应该变成“1 Kb”,1024*1024应该变成“1 Mb”。

我有点厌倦了为每个项目写这个实用方法。在Apache Commons中有这样的静态方法吗?


当前回答

字节单位允许你这样做:

long input1 = 1024;
long input2 = 1024 * 1024;

Assert.assertEquals("1 KiB", BinaryByteUnit.format(input1));
Assert.assertEquals("1 MiB", BinaryByteUnit.format(input2));

Assert.assertEquals("1.024 KB", DecimalByteUnit.format(input1, "#.0"));
Assert.assertEquals("1.049 MB", DecimalByteUnit.format(input2, "#.000"));

NumberFormat format = new DecimalFormat("#.#");
Assert.assertEquals("1 KiB", BinaryByteUnit.format(input1, format));
Assert.assertEquals("1 MiB", BinaryByteUnit.format(input2, format));

我写了另一个叫做storage-units的库,它允许你这样做:

String formattedUnit1 = StorageUnits.formatAsCommonUnit(input1, "#");
String formattedUnit2 = StorageUnits.formatAsCommonUnit(input2, "#");
String formattedUnit3 = StorageUnits.formatAsBinaryUnit(input1);
String formattedUnit4 = StorageUnits.formatAsBinaryUnit(input2);
String formattedUnit5 = StorageUnits.formatAsDecimalUnit(input1, "#.00", Locale.GERMAN);
String formattedUnit6 = StorageUnits.formatAsDecimalUnit(input2, "#.00", Locale.GERMAN);
String formattedUnit7 = StorageUnits.formatAsBinaryUnit(input1, format);
String formattedUnit8 = StorageUnits.formatAsBinaryUnit(input2, format);

Assert.assertEquals("1 kB", formattedUnit1);
Assert.assertEquals("1 MB", formattedUnit2);
Assert.assertEquals("1.00 KiB", formattedUnit3);
Assert.assertEquals("1.00 MiB", formattedUnit4);
Assert.assertEquals("1,02 kB", formattedUnit5);
Assert.assertEquals("1,05 MB", formattedUnit6);
Assert.assertEquals("1 KiB", formattedUnit7);
Assert.assertEquals("1 MiB", formattedUnit8);

如果你想强制某个单位,可以这样做:

String formattedUnit9 = StorageUnits.formatAsKibibyte(input2);
String formattedUnit10 = StorageUnits.formatAsCommonMegabyte(input2);

Assert.assertEquals("1024.00 KiB", formattedUnit9);
Assert.assertEquals("1.00 MB", formattedUnit10);

其他回答

你可以使用StringUtils的TraditionalBinarPrefix:

public static String humanReadableInt(long number) {
    return TraditionalBinaryPrefix.long2String(number, ””, 1);
}

现在有一个包含单元格式的库可用。我把它添加到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

我们可以完全避免使用缓慢的Math.pow()和Math.log()方法,而不会牺牲简单性,因为单位之间的因子(例如,B, KB, MB等)是1024,即2^10。Long类有一个方便的numberofleadingzero()方法,我们可以用它来告诉大小值落在哪个单元中。

重点:大小单位的距离为10位(1024 = 2^10),这意味着最高位的位置-换句话说,前导零的数量-相差10(字节= KB*1024, KB = MB*1024,等等)。

前导零数与大小单位的相关性:

# of leading 0's Size unit
>53 B (Bytes)
>43 KB
>33 MB
>23 GB
>13 TB
>3 PB
<=3 EB

最终代码:

public static String formatSize(long v) {
    if (v < 1024) return v + " B";
    int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
    return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
}
filename=filedilg.getSelectedFile().getAbsolutePath();
File file=new File(filename);

String disp=FileUtils.byteCountToDisplaySize(file.length());
System.out.println("THE FILE PATH IS "+file+"THIS File SIZE IS IN MB "+disp);

创建接口:

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