如何在 Java 中将字节大小转换为人类可读的格式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3758606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to convert byte size into human readable format in Java?
提问by Igor Mukhin
How to convert byte size into human-readable format in Java? Like 1024 should become "1 Kb" and 1024*1024 should become "1 Mb".
如何在 Java 中将字节大小转换为人类可读的格式?比如 1024 应该变成“1 Kb”,而 1024*1024 应该变成“1 Mb”。
I am kind of sick of writing this utility method for each project. Are there any static methods in Apache Commonsfor this?
我有点厌倦为每个项目编写这种实用方法。Apache Commons 中是否有任何静态方法?
采纳答案by aioobe
Fun fact:The original snippet posted here was the most copied Java snippet of all time on Stack Overflow, and it was flawed. It was fixed but it got messy.
Full story in this article: The most copied StackOverflow snippet of all time is flawed!
有趣的事实:此处发布的原始代码段是 Stack Overflow 上有史以来复制最多的 Java 代码段,并且存在缺陷。它是固定的,但它变得凌乱。
Source: Formatting byte size to human readable format | Programming.Guide
SI (1 k = 1,000)
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());
}
Binary (1 K = 1,024)
二进制 (1 K = 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());
}
Example output:
示例输出:
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)
回答by Sean Patrick Floyd
I asked the same Question recently:
我最近问了同样的问题:
Format file size as MB, GB etc
While there is no out-of-the-box answer, I can live with the solution:
虽然没有现成的答案,但我可以接受以下解决方案:
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;
}
Test code:
测试代码:
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));
}
}
Output (on my German Locale):
输出(在我的德语语言环境中):
1 B
4,2 KB
41,4 MB
3,3 GB
Edit: I have opened an Issue requesting this functionality for Google Guava. Perhaps someone would care to support it.
编辑:我打开了一个问题,要求为 Google Guava 提供此功能。也许有人会关心支持它。
回答by user601806
FileUtils.byteCountToDisplaySize(long size)
would work if your project can depend on org.apache.commons.io
.
FileUtils.byteCountToDisplaySize(long size)
如果您的项目可以依赖于org.apache.commons.io
.
回答by Lars Bohl
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);
}
回答by Mano Chella
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);
回答by XXX
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 "???";
}
回答by android developer
If you use Android, you can simply use android.text.format.Formatter.formatFileSize().
如果您使用 Android,您可以简单地使用android.text.format.Formatter.formatFileSize()。
Alternativey, here's a solution based on 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;
}
Or in Kotlin:
或者在 Kotlin 中:
/**
* formats the bytes to a human readable format
*
* @param si true if each kilo==1000, false if kilo==1024
*/
@SuppressLint("DefaultLocale")
fun humanReadableByteCount(bytes: Long, si: Boolean): String? {
val unit = if (si) 1000.0 else 1024.0
if (bytes < unit)
return "$bytes B"
var result = bytes.toDouble()
val unitsToUse = (if (si) "k" else "K") + "MGTPE"
var i = 0
val unitsCount = unitsToUse.length
while (true) {
result /= unit
if (result < unit || i == unitsCount - 1)
break
++i
}
return with(StringBuilder(9)) {
append(String.format("%.1f ", result))
append(unitsToUse[i])
if (si) append('B') else append("iB")
}.toString()
}
回答by icza
We can completely avoid using the slow Math.pow()
and Math.log()
methods without sacrificing simplicity since the factor between the units (e.g. B, KB, MB etc.) is 1024 which is 2^10. The Long
class has a handy numberOfLeadingZeros()
method which we can use to tell which unit the size value falls in.
我们可以在不牺牲简单性的情况下完全避免使用慢速Math.pow()
和Math.log()
方法,因为单位(例如 B、KB、MB 等)之间的因子是 1024,即 2^10。该Long
班有一个方便的numberOfLeadingZeros()
,我们可以用它来判断哪些单元大小值落在方法。
Key point:Size units have a distance of 10 bits (1024=2^10) meaning the position of the highest 1 bit - or in other words the number of leading zeros- differ by 10 (Bytes=KB*1024, KB=MB*1024 etc.).
关键点:大小单位有 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));
}
回答by AZ_
Use Android builtin Class
使用 Android 内置类
For Android there is a class Formatter. Just one line of code and you are done.
对于 Android,有一个类Formatter。只需一行代码,您就完成了。
android.text.format.Formatter.formatShortFileSize(activityContext, bytes);
It is like formatFileSize()
, but trying to generate shorter numbers (showing fewer decimals).
就像formatFileSize()
,但试图生成更短的数字(显示更少的小数)。
android.text.format.Formatter.formatFileSize(activityContext, bytes);
Formats a content size to be in the form of bytes, kilobytes, megabytes, etc.
将内容大小格式化为字节、千字节、兆字节等形式。
回答by Vishwajit R. Shinde
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;
}
Just add more file units (if any missing), and you will see unit size upto that unit (if your file has that much length) System.out.println("File size in proper format: " + bytes + " " + fileSizeUnits[index]); sizeToReturn = String.valueOf(bytes) + " " + fileSizeUnits[index]; return sizeToReturn; }
只需添加更多文件单元(如果有任何丢失),您将看到该单元的单元大小(如果您的文件有那么多长度) System.out.println("正确格式的文件大小:" + bytes + " " + fileSizeUnits [指数]); sizeToReturn = String.valueOf(bytes) + " " + fileSizeUnits[index]; 返回大小返回;}