如何在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

其他回答

datasize至少在计算中可以满足这个需求。那么一个简单的装饰器就可以了。

我最近问了同样的问题:

格式文件大小为MB, GB等。

虽然没有开箱即用的答案,但我可以接受这个解决方案:

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;

public static String convertToStringRepresentation(final long value){
    final long[] dividers = new long[] { T, G, M, K, 1 };
    final String[] units = new String[] { "TB", "GB", "MB", "KB", "B" };
    if(value < 1)
        throw new IllegalArgumentException("Invalid file size: " + value);
    String result = null;
    for(int i = 0; i < dividers.length; i++){
        final long divider = dividers[i];
        if(value >= divider){
            result = format(value, divider, units[i]);
            break;
        }
    }
    return result;
}

private static String format(final long value,
    final long divider,
    final String unit){
    final double result =
        divider > 1 ? (double) value / (double) divider : (double) value;
    return new DecimalFormat("#,##0.#").format(result) + " " + unit;
}

测试代码:

public static void main(final String[] args){
    final long[] l = new long[] { 1l, 4343l, 43434334l, 3563543743l };
    for(final long ll : l){
        System.out.println(convertToStringRepresentation(ll));
    }
}

输出(在我的德语地区):

1 B
4,2 KB
41,4 MB
3,3 GB

我已经打开了一个问题,要求谷歌番石榴的这个功能。也许有人愿意支持它。

试试JSR 363。它的单元扩展模块,如Unicode CLDR(在GitHub: uom-systems中),为您完成所有这些。

你可以使用每个实现中包含的MetricPrefix或BinaryPrefix(与上面的一些例子相比),如果你在印度或附近的国家生活和工作,IndianPrefix(也在uom-系统的公共模块中)允许你使用和格式化“千万字节”或“Lakh字节”。

也许你可以使用下面的代码(在c#中):

long Kb = 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 size.ToString() + " byte";

if (size < Mb)  return (size / Kb).ToString("###.##") + " Kb.";
if (size < Gb)  return (size / Mb).ToString("###.##") + " Mb.";
if (size < Tb)  return (size / Gb).ToString("###.##") + " Gb.";
if (size < Pb)  return (size / Tb).ToString("###.##") + " Tb.";
if (size < Eb)  return (size / Pb).ToString("###.##") + " Pb.";
if (size >= Eb) return (size / Eb).ToString("###.##") + " Eb.";

return "invalid size";

下面是上面Java正确的共识答案的c# .NET等价版本 (下面还有一个代码更短的例子):

    public static String BytesNumberToHumanReadableString(long bytes, bool SI1000orBinary1024)
    {
        int unit = SI1000orBinary1024 ? 1000 : 1024;
        if (bytes < unit)
            return bytes + " B";

        int exp = (int)(Math.Log(bytes) / Math.Log(unit));
        String pre = (SI1000orBinary1024 ? "kMGTPE" : "KMGTPE")[(exp - 1)] + (SI1000orBinary1024 ? "" : "i");
        return String.Format("{0:F1} {1}B", bytes / Math.Pow(unit, exp), pre);
    }

从技术上讲,如果我们坚持使用国际单位制,这个程序适用于任何常规的数字使用。专家们还给出了许多不错的答案。假设您正在对gridview上的数字进行数据绑定,有必要从它们中查看性能优化例程。

PS:这个帖子是因为当我在做一个c#项目时,这个问题/答案出现在谷歌搜索的顶部。