How to convert byte size into human readable format in java?
在Java中如何将字节大小转换为人类可读格式?像1024应该变成"1KB",而1024*1024应该变成"1MB"。
我有点讨厌为每个项目编写这种实用方法。在ApacheCommons中,是否有任何静态方法可以实现这一点?
这是我的做法(没有循环和处理国际单位和二进制单位):
1 2 3 4 5 6 7 | 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); } |
实例输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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:将字节大小格式化为人类可读格式
如果您的项目可以依赖于
此方法的JavaDoc
使用Android内置类
对于Android,有一个类格式化程序。只有一个类似的代码,你就完成了。
1 | android.text.format.Formatter.formatShortFileSize(activityContext, bytes); |
它与
1 | android.text.format.Formatter.formatFileSize(activityContext, bytes); |
将内容大小格式化为字节、千字节、兆字节等形式。
我们可以完全避免使用缓慢的
关键点:大小单位的距离为10位(1024=2^10),表示最高1位的位置,或者换句话说,前导零的数量相差10位(字节=kb*1024,kb=mb*1024等)。
前导零个数与大小单位的相关性:
1 2 3 4 5 6 7 8 9 | # of leading 0's Size unit ------------------------------- >53 B (Bytes) >43 KB >33 MB >23 GB >13 TB >3 PB <=2 EB |
最终代码:
1 2 3 4 5 |
我最近问了同样的问题:
将文件大小格式化为MB、GB等
虽然没有现成的答案,但我可以接受这个解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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; } |
测试代码:
1 2 3 4 5 6 |
输出(在我的德语区域设置上):
1 2 3 4 | 1 B 4,2 KB 41,4 MB 3,3 GB |
编辑:我打开了一个问题,要求谷歌瓜娃提供这个功能。也许有人愿意支持它。
这是Aiobe答案的修改版本。
变化:
Locale 参数,因为有些语言使用. 和其他, 作为小数点。- 人类可读代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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); } |
如果使用Android,只需使用formatter.formatfilesize()。
另外,这里有一个基于这个流行帖子的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /** * 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; } |
1 2 3 4 5 6 7 8 9 10 11 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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"???"; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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"; } } |
字节单位允许您这样做:
1 2 3 4 5 6 7 8 9 10 11 12 | 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)); |
我写了另一个库,叫做存储单元,它允许你这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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); |
如果要强制某个单位,请执行以下操作:
1 2 3 4 5 |
现在有一个库包含单位格式。我将它添加到Triava库中,因为现有的唯一一个库似乎是用于Android的库。
它可以在3个不同的系统(si、iec、jedec)和各种输出选项中以任意精度格式化数字。以下是Triava单元测试的一些代码示例:
1 2 3 4 | UnitFormatter.formatAsUnit(1126, UnitSystem.SI,"B"); // ="1.13kB" UnitFormatter.formatAsUnit(2094, UnitSystem.IEC,"B"); // ="2.04KiB" |
打印精确的千、兆值(此处W=瓦):
1 2 | UnitFormatter.formatAsUnits(12_000_678, UnitSystem.SI,"W",","); // ="12MW, 678W" |
您可以通过decimalFormat自定义输出:
1 2 |
对于对kilo或mega值的任意操作,可以将其拆分为组件:
1 2 3 | UnitComponent uc = new UnitComponent(123_345_567_789L, UnitSystem.SI); int kilos = uc.kilo(); // 567 int gigas = uc.giga(); // 123 |
我知道更新这篇文章太迟了!但我对这件事很感兴趣:
创建接口:
1 2 3 4 |
创建StorageUnits类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 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.#"); } } |
称之为:
1 2 3 4 5 6 |
输出:
1 2 | 21.4kB 2GB |
这里是上面关于Java正确一致答案的C...NET等价物。(下面还有一个代码较短的代码)
1 2 3 4 5 6 7 8 9 | 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); } |
从技术上讲,如果我们坚持使用国际单位制,这个程序适用于任何经常使用的数字。专家们还有许多其他的好答案。假设您正在网格视图上进行数字的数据绑定,从中检查性能优化的例程是值得的。
PS:发布是因为这个问题/答案在我做C项目的时候出现在谷歌搜索上。
在不太可能的情况下,它可以节省一些时间,或者只是为了好玩,这里有一个Go版本。为了简单起见,我只包括二进制输出案例。
1 2 3 4 5 6 7 8 9 10 11 12 | 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) } |
1 2 3 4 5 6 7 8 9 10 |
只需添加更多的文件单位(如果有丢失的话),你就会看到单位大小达到那个单位(如果你的文件有那么长的长度)system.out.println("正确格式的文件大小:"+bytes+""+filesizeUnits[索引]);sizeToReturn=string.valueof(bytes)+""+filesizeUnits[索引];返回大小返回;}
使用下面的函数可以获得准确的信息,这些信息是根据
1 | getFullMemoryUnit(): Total: [123 MB], Max: [1 GB, 773 MB, 512 KB], Free: [120 MB, 409 KB, 304 Bytes] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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-
1 | getMemoryUnit(): Total: [123.0 MB], Max: [1.8 GB], Free: [120.4 MB] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } |
上述方法的示例用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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] ", heapSize, heapMaxSize, heapFreeSize); System.out.format("getMemoryUnit(): Total: [%s], Max: [%s], Free: [%s] ", getMemoryUnit(heapSize), getMemoryUnit(heapMaxSize), getMemoryUnit(heapFreeSize)); System.out.format("getFullMemoryUnit(): Total: [%s], Max: [%s], Free: [%s] ", getFullMemoryUnit(heapSize), getFullMemoryUnit(heapMaxSize), getFullMemoryUnit(heapFreeSize)); } |
高于格式的字节数
1 | Total: [128974848], Max: [1884815360], Free: [126248240] |
为了以人类可读的格式显示时间,请使用此函数
你试过JSR 363吗?它的单元扩展模块,比如unicode cldr(在github:uom系统中),为您做所有这些。
您可以使用每个实现中包含的
您可以使用StringUtils的
1 2 3 | public static String humanReadableInt(long number) { return TraditionalBinaryPrefix.long2String(number,"",1); } |
1 2 3 4 5 |
也许您可以使用此代码(在C中):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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"; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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); } } } } } |