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

如何在Java中将字节大小转换为可读格式? 像1024应该成为“1 Kb”和1024 * 1024应该成为“1Mb”。

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

这里是我的去(没有循环,处理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:将字节大小格式化为可读格式

FileUtils.byteCountToDisplaySize(long size)将工作,如果您的项目可以依赖于org.apache.commons.io

这个方法的JavaDoc

使用Android内置类

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

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

这就像formatFileSize() ,但试图产生更短的数字(显示更less的小数)。

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

将内容大小格式化为字节,千字节,兆字节等forms

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

关键点:大小单位有10位(1024 = 2 ^ 10)的距离,这意味着最高1位的位置 – 换句话说,前导零数量相差10(Bytes = KB * 1024,KB = MB * 1024等)。

前导零个数和大小单位之间的相关性:

 # of leading 0's Size unit ------------------------------- >53 B (Bytes) >43 KB >33 MB >23 GB >13 TB >3 PB <=2 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)); } 

最近我问了同样的问题:

格式文件大小为MB,GB等

虽然没有现成的答案,我可以接受解决scheme:

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

testing代码:

 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 

编辑:我已经打开一个问题,要求谷歌Guava的这个function 。 也许有人会关心支持它。

 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); } 
  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 "???"; } 

这是aioobe的答案的修改版本。

变化:

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

如果你使用Android,你可以简单地使用Formatter.formatFileSize() 。

另外,这里有一个基于这个热门文章的解决scheme:

  /** * 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; } 
  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"; } } 

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

它可以用三种不同的系统(SI,IEC,JEDEC)和各种输出选项以任意精度格式化数字。 以下是triavaunit testing的一些代码示例:

 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" 

对于千位或大数值的任意操作,可以将它们分成组件:

 UnitComponent uc = new UnitComponent(123_345_567_789L, UnitSystem.SI); int kilos = uc.kilo(); // 567 int gigas = uc.giga(); // 123 

字节单位允许你这样做:

 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); 
 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 [指数]); sizeToReturn = String.valueOf(bytes)+“”+ fileSizeUnits [index]; 返回sizeToReturn; }

这里是C#.net等同于上面的Java正确答案的答案。 (下面有另一个更短的代码)

  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单位,这个例程适用于任何经常使用的数字。 还有很多来自专家的好答案。 假设你在GridView上进行数字数据绑定,它的价值是从它们中检查性能优化的例程。

PS:发布是因为这个问题/答案出现在谷歌search上,而我正在做C#项目。

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

你有没有试过JSR 363 ? 它的单位扩展模块,如Unicode CLDR(在GitHub:uom-systems中 )可以完成所有的工作。

您可以使用包含在每个实现或BinaryPrefix (与上面的一些示例类似),并且如果您在印度或附近的国家生活和工作, IndianPrefix (也在uom-systems的通用模块中)允许您使用格式“Crore字节”或“Lakh Bytes”。

我知道现在更新这个post为时已晚! 但是我有一些这样的乐趣:

创build一个界面:

 public interface IUnits { public String format(long size, String pattern); public long getUnitSize(); } 

创buildStorageUnits类:

 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 

你可以使用StringUtils的TraditionalBinarPrefix

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