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

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

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


当前回答

使用下面的函数来获得确切的信息。它是基于atm_cashwithdraw概念生成的。

getFullMemoryUnit(): Total: [123 MB], Max: [1 GB, 773 MB, 512 KB], Free: [120 MB, 409 KB, 304 Bytes]
public static String getFullMemoryUnit(long unit) {
    long BYTE = 1024, KB = BYTE, MB = KB * KB, GB = MB * KB, TB = GB * KB;
    long KILO_BYTE, MEGA_BYTE = 0, GIGA_BYTE = 0, TERA_BYTE = 0;
    unit = Math.abs(unit);
    StringBuffer buffer = new StringBuffer();
    if ( unit / TB > 0 ) {
        TERA_BYTE = (int) (unit / TB);
        buffer.append(TERA_BYTE+" TB");
        unit -= TERA_BYTE * TB;
    }
    if ( unit / GB > 0 ) {
        GIGA_BYTE = (int) (unit / GB);
        if (TERA_BYTE != 0) buffer.append(", ");
        buffer.append(GIGA_BYTE+" GB");
        unit %= GB;
    }
    if ( unit / MB > 0 ) {
        MEGA_BYTE = (int) (unit / MB);
        if (GIGA_BYTE != 0) buffer.append(", ");
        buffer.append(MEGA_BYTE+" MB");
        unit %= MB;
    }
    if ( unit / KB > 0 ) {
        KILO_BYTE = (int) (unit / KB);
        if (MEGA_BYTE != 0) buffer.append(", ");
        buffer.append(KILO_BYTE+" KB");
        unit %= KB;
    }
    if ( unit > 0 ) buffer.append(", "+unit+" Bytes");
    return buffer.toString();
}

我刚刚修改了facebookarchive-StringUtils的代码以获得以下格式。与使用apache.hadoop-StringUtils时得到的格式相同

getMemoryUnit(): Total: [123.0 MB], Max: [1.8 GB], Free: [120.4 MB]
public static String getMemoryUnit(long bytes) {
    DecimalFormat oneDecimal = new DecimalFormat("0.0");
    float BYTE = 1024.0f, KB = BYTE, MB = KB * KB, GB = MB * KB, TB = GB * KB;
    long absNumber = Math.abs(bytes);
    double result = bytes;
    String suffix = " Bytes";
    if (absNumber < MB) {
        result = bytes / KB;
        suffix = " KB";
    } else if (absNumber < GB) {
        result = bytes / MB;
        suffix = " MB";
    } else if (absNumber < TB) {
        result = bytes / GB;
        suffix = " GB";
    }
    return oneDecimal.format(result) + suffix;
}

以上方法的使用示例:

public static void main(String[] args) {
    Runtime runtime = Runtime.getRuntime();
    int availableProcessors = runtime.availableProcessors();

    long heapSize = Runtime.getRuntime().totalMemory();
    long heapMaxSize = Runtime.getRuntime().maxMemory();
    long heapFreeSize = Runtime.getRuntime().freeMemory();

    System.out.format("Total: [%s], Max: [%s], Free: [%s]\n", heapSize, heapMaxSize, heapFreeSize);
    System.out.format("getMemoryUnit(): Total: [%s], Max: [%s], Free: [%s]\n",
            getMemoryUnit(heapSize), getMemoryUnit(heapMaxSize), getMemoryUnit(heapFreeSize));
    System.out.format("getFullMemoryUnit(): Total: [%s], Max: [%s], Free: [%s]\n",
            getFullMemoryUnit(heapSize), getFullMemoryUnit(heapMaxSize), getFullMemoryUnit(heapFreeSize));
}

字节来获取上面的格式

Total: [128974848], Max: [1884815360], Free: [126248240]

为了以人类可读的格式显示时间,请使用函数millisToShortDHMS(长持续时间)。

其他回答

public String humanReadable(long size) {
    long limit = 10 * 1024;
    long limit2 = limit * 2 - 1;
    String negative = "";
    if(size < 0) {
        negative = "-";
        size = Math.abs(size);
    }

    if(size < limit) {
        return String.format("%s%s bytes", negative, size);
    } else {
        size = Math.round((double) size / 1024);
        if (size < limit2) {
            return String.format("%s%s kB", negative, size);
        } else {
            size = Math.round((double)size / 1024);
            if (size < limit2) {
                return String.format("%s%s MB", negative, size);
            } else {
                size = Math.round((double)size / 1024);
                if (size < limit2) {
                    return String.format("%s%s GB", negative, size);
                } else {
                    size = Math.round((double)size / 1024);
                        return String.format("%s%s TB", negative, size);
                }
            }
        }
    }
}
    public static String floatForm (double d)
    {
       return new DecimalFormat("#.##").format(d);
    }


    public static String bytesToHuman (long size)
    {
        long Kb = 1  * 1024;
        long Mb = Kb * 1024;
        long Gb = Mb * 1024;
        long Tb = Gb * 1024;
        long Pb = Tb * 1024;
        long Eb = Pb * 1024;

        if (size <  Kb)                 return floatForm(        size     ) + " byte";
        if (size >= Kb && size < Mb)    return floatForm((double)size / Kb) + " Kb";
        if (size >= Mb && size < Gb)    return floatForm((double)size / Mb) + " Mb";
        if (size >= Gb && size < Tb)    return floatForm((double)size / Gb) + " Gb";
        if (size >= Tb && size < Pb)    return floatForm((double)size / Tb) + " Tb";
        if (size >= Pb && size < Eb)    return floatForm((double)size / Pb) + " Pb";
        if (size >= Eb)                 return floatForm((double)size / Eb) + " Eb";

        return "???";
    }

有趣的事实:这里发布的原始代码片段是Stack Overflow上被复制最多的Java代码片段,它是有缺陷的。它被修好了,但却变得一团糟。 本文的完整故事:有史以来复制最多的堆栈溢出代码片段是有缺陷的!

来源:格式化字节大小到人类可读的格式|编程。指南

SI(1 k = 1,000)

public static String humanReadableByteCountSI(long bytes) {
    if (-1000 < bytes && bytes < 1000) {
        return bytes + " B";
    }
    CharacterIterator ci = new StringCharacterIterator("kMGTPE");
    while (bytes <= -999_950 || bytes >= 999_950) {
        bytes /= 1000;
        ci.next();
    }
    return String.format("%.1f %cB", bytes / 1000.0, ci.current());
}

二进制(1's = 1,024)

public static String humanReadableByteCountBin(long bytes) {
    long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
    if (absB < 1024) {
        return bytes + " B";
    }
    long value = absB;
    CharacterIterator ci = new StringCharacterIterator("KMGTPE");
    for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
        value >>= 10;
        ci.next();
    }
    value *= Long.signum(bytes);
    return String.format("%.1f %ciB", value / 1024.0, ci.current());
}

示例输出:

                             SI     BINARY

                  0:        0 B        0 B
                 27:       27 B       27 B
                999:      999 B      999 B
               1000:     1.0 kB     1000 B
               1023:     1.0 kB     1023 B
               1024:     1.0 kB    1.0 KiB
               1728:     1.7 kB    1.7 KiB
             110592:   110.6 kB  108.0 KiB
            7077888:     7.1 MB    6.8 MiB
          452984832:   453.0 MB  432.0 MiB
        28991029248:    29.0 GB   27.0 GiB
      1855425871872:     1.9 TB    1.7 TiB
9223372036854775807:     9.2 EB    8.0 EiB   (Long.MAX_VALUE)

创建接口:

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
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;
}

只需添加更多的文件单元(如果有任何缺失),你将看到单元大小达到该单元(如果你的文件有那么长):