首页 文章

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

提问于
浏览
454

如何在Java中将字节大小转换为人类可读的格式?像1024应该变成“1 Kb”而1024 * 1024应该变成“1 Mb” .

我有点厌倦为每个项目编写这个实用程序方法 . Apache Commons中是否有任何静态方法?

20 回答

  • 0

    在偶然的情况下,它可以节省一些时间,或者只是为了一点乐趣,这里是Go版本 . 为简单起见,我只包含了二进制输出案例 .

    func sizeOf(bytes int64) string {
        const unit = 1024
        if bytes < unit {
            return fmt.Sprintf("%d B", bytes)
        }
    
        fb := float64(bytes)
        exp := int(math.Log(fb) / math.Log(unit))
        pre := "KMGTPE"[exp-1]
        div := math.Pow(unit, float64(exp))
        return fmt.Sprintf("%.1f %ciB", fb / div, pre)
    }
    
  • 0

    你可以使用StringUtilsTraditionalBinarPrefix

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

    如果您的项目可以依赖 org.apache.commons.ioFileUtils.byteCountToDisplaySize(long size) 将起作用 .

    JavaDoc for this method

  • 22

    我知道现在更新这篇文章已经太晚了!但我对此有一些乐趣:

    创建一个界面:

    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
    
  • 7
    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(“文件大小格式正确:”bytes“”fileSizeUnits [index] ); sizeToReturn = String.valueOf(bytes)“”fileSizeUnits [index]; return sizeToReturn; }

  • 7

    这是aioobe's answer的修改版本 .

    变化:

    • 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);
    }
    
  • 0

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

    您可以使用 MetricPrefix 包含在每个实现中或 BinaryPrefix (与上面的一些示例相比),如果您是在印度或附近国家生活和工作, IndianPrefix (也在uom系统的通用模块中)允许您使用和格式化"Crore Bytes"或"Lakh Bytes" .

  • 257

    Byte Units允许你这样做:

    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);
    
  • 3
    private static final String[] Q = new String[]{"", "K", "M", "G", "T", "P", "E"};
    
    public String getAsString(long bytes)
    {
        for (int i = 6; i > 0; i--)
        {
            double step = Math.pow(1024, i);
            if (bytes > step) return String.format("%3.1f %s", bytes / step, Q[i]);
        }
        return Long.toString(bytes);
    }
    
  • 39
    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 "???";
        }
    
  • 3
    private String bytesIntoHumanReadable(long bytes) {
            long kilobyte = 1024;
            long megabyte = kilobyte * 1024;
            long gigabyte = megabyte * 1024;
            long terabyte = gigabyte * 1024;
    
            if ((bytes >= 0) && (bytes < kilobyte)) {
                return bytes + " B";
    
            } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
                return (bytes / kilobyte) + " KB";
    
            } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
                return (bytes / megabyte) + " MB";
    
            } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
                return (bytes / gigabyte) + " GB";
    
            } else if (bytes >= terabyte) {
                return (bytes / terabyte) + " TB";
    
            } else {
                return bytes + " Bytes";
            }
        }
    
  • 2

    这是我的去处(没有循环并处理SI单位和二进制单位):

    public static String humanReadableByteCount(long bytes, boolean si) {
        int unit = si ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }
    

    输出示例:

    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)
    

    相关文章:Java: Formatting byte size to human readable format

  • 1

    现在有一个可用的库包含单元格式 . 我将它添加到triava库中,因为唯一的其他现有库似乎是Android的库 .

    它可以在3种不同的系统(SI,IEC,JEDEC)和各种输出选项中以任意精度格式化数字 . 以下是triava unit tests中的一些代码示例:

    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
    
  • 1

    Use Android builtin Class

    对于Android,有一个类Formatter . 就像代码一样,你就完成了 .

    android.text.format.Formatter.formatShortFileSize(activityContext, bytes);
    

    它就像 formatFileSize() ,但试图产生更短的数字(显示更少的小数) .

    android.text.format.Formatter.formatFileSize(activityContext, bytes);
    

    格式化内容大小为字节,千字节,兆字节等形式 .

  • 1132

    如果您使用Android,则只需使用Formatter.formatFileSize()即可 .

    另类,这是基于this popular post的解决方案:

    /**
       * formats the bytes to a human readable format
       *
       * @param si true if each kilo==1000, false if kilo==1024
       */
      @SuppressLint("DefaultLocale")
      public static String humanReadableByteCount(final long bytes,final boolean si)
        {
        final int unit=si ? 1000 : 1024;
        if(bytes<unit)
          return bytes+" B";
        double result=bytes;
        final String unitsToUse=(si ? "k" : "K")+"MGTPE";
        int i=0;
        final int unitsCount=unitsToUse.length();
        while(true)
          {
          result/=unit;
          if(result<unit)
            break;
          // check if we can go further:
          if(i==unitsCount-1)
            break;
          ++i;
          }
        final StringBuilder sb=new StringBuilder(9);
        sb.append(String.format("%.1f ",result));
        sb.append(unitsToUse.charAt(i));
        if(si)
          sb.append('B');
        else sb.append('i').append('B');
        final String resultStr=sb.toString();
        return resultStr;
        }
    
  • 2
    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);
    
  • 6

    我们可以完全避免使用慢速 Math.pow()Math.log() 方法而不牺牲简单性,因为单位之间的因子(例如B,KB,MB等)是1024,即2 ^ 10 . Long 类有一个方便的 numberOfLeadingZeros() 方法,我们可以用它来判断大小值属于哪个单位 .

    Key point: 大小单位的距离为10位(1024 = 2 ^ 10),这意味着最高1位的位置 - 或者换言之,前导零的数量 - 相差10(字节= KB * 1024,KB = MB * 1024)等等 . ) .

    Correlation between number of leading zeros and size unit:

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

    The final code:

    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));
    }
    
  • 1

    我最近问了同一个问题:

    Format file size as MB, GB etc

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

    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
    

    编辑:我已经打开Issue requesting this functionality for Google Guava . 也许有人会关心它 .

  • 0

    也许你可以使用这个代码(在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";
    
  • 5

    这是上面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);
        }
    

    从技术上讲,如果我们坚持SI单位,这个例程适用于任何经常使用的数字 . 专家还有许多其他好的答案 . 假设您正在对gridviews上的数字进行数据绑定,那么从它们中检查性能优化的例程是值得的 .

    PS:发布是因为当我在做C#项目时,这个问题/答案在谷歌搜索中排在首位 .

相关问题