public String size(int size){
String hrSize = \"\";
int k = size;
double m = size/1024;
double g = size/1048576;
double t = size/1073741824;
Its not easy to get that right. Rohit Jain mentioned the integer operation. Also rounding can be an issue, as always rounding down may not be desirable. I would advise to go for an available solution like in the triava library.
It can format numbers with arbitrary precision, in 3 different systems (SI, IEC, JEDEC) and various output options. Here are some code examples from the triava unit tests:
UnitFormatter.formatAsUnit(1126, UnitSystem.SI, "B");
// = "1.13kB"
UnitFormatter.formatAsUnit(2094, UnitSystem.IEC, "B");
// = "2.04KiB"
Printing exact kilo, mega values (here with W = Watt):
UnitFormatter.formatAsUnits(12_000_678, UnitSystem.SI, "W", ", ");
// = "12MW, 678W"
You can pass a DecimalFormat to customize the output:
UnitFormatter.formatAsUnit(2085, UnitSystem.IEC, "B", new DecimalFormat("0.0000"));
// = "2.0361KiB"
For arbitrary operations on kilo or mega values, you can split them into components:
UnitComponent uc = new UnitComponent(123_345_567_789L, UnitSystem.SI);
int kilos = uc.kilo(); // 567
int gigas = uc.giga(); // 123
A modified version. Only calls format once. Includes "Bytes".
public static String formatFileSize(long size) {
String hrSize = null;
double b = size;
double k = size/1024.0;
double m = ((size/1024.0)/1024.0);
double g = (((size/1024.0)/1024.0)/1024.0);
double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0);
DecimalFormat dec = new DecimalFormat("0.00");
if ( t>1 ) {
hrSize = dec.format(t).concat(" TB");
} else if ( g>1 ) {
hrSize = dec.format(g).concat(" GB");
} else if ( m>1 ) {
hrSize = dec.format(m).concat(" MB");
} else if ( k>1 ) {
hrSize = dec.format(k).concat(" KB");
} else {
hrSize = dec.format(b).concat(" Bytes");
}
return hrSize;
}
class ConverterUtils{
public static void main(String[] args) {
System.out.println(getSize(1234567));
}
public static String getSize(long size) {
String s = "";
double kb = size / 1024;
double mb = kb / 1024;
double gb = mb / 1024;
double tb = gb / 1024;
if(size < 1024L) {
s = size + " Bytes";
} else if(size >= 1024 && size < (1024L * 1024)) {
s = String.format("%.2f", kb) + " KB";
} else if(size >= (1024L * 1024) && size < (1024L * 1024 * 1024)) {
s = String.format("%.2f", mb) + " MB";
} else if(size >= (1024L * 1024 * 1024) && size < (1024L * 1024 * 1024 * 1024)) {
s = String.format("%.2f", gb) + " GB";
} else if(size >= (1024L * 1024 * 1024 * 1024)) {
s = String.format("%.2f", tb) + " TB";
}
return s;
}
}
To better understand - https://www.techspot.com/news/68482-quickly-convert-between-storage-size-units-kb-mb.html
I love this:
public static String getDynamicSpace(long diskSpaceUsed)
{
if (diskSpaceUsed <= 0) {
return "0";
}
final String[] units = new String[] { "B", "KiB", "MiB", "GiB", "TiB" };
int digitGroups = (int) (Math.log10(diskSpaceUsed) / Math.log10(1024));
return new DecimalFormat("#,##0.#").format(diskSpaceUsed / Math.pow(1024, digitGroups))
+ " " + units[digitGroups];
}
bickster's answer works quite alright but the problem with it is that it returns results like 45.00 Bytes
and 12.00 KB
. In my opinion, the last decimal digits should be removed if they are zeros. So instead of 45.00 Bytes
and 12.00 KB
, you get 45 B
and 12 KB
(notice that Bytes
has been changed to B
. This is just for uniformity since we have KB, MB etc and not Kilobytes, Megabytes etc).
private boolean isDouble(double value) {
if (value % 1 == 0) {
Log.d(TAG, "value is " + value + " and is not double");
return false;
} else {
Log.d(TAG, "value is " + value + " and is double");
return true;
}
}
The above method simply checks if the value has zeros as decimal digits.
private String formatFileSize(long size) {
String hrSize = null;
double b = size;
double k = size/1024.0;
double m = ((size/1024.0)/1024.0);
double g = (((size/1024.0)/1024.0)/1024.0);
double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0);
DecimalFormat dec1 = new DecimalFormat("0.00");
DecimalFormat dec2 = new DecimalFormat("0");
if (t>1) {
hrSize = isDouble(t) ? dec1.format(t).concat(" TB") : dec2.format(t).concat(" TB");
} else if (g>1) {
hrSize = isDouble(g) ? dec1.format(g).concat(" GB") : dec2.format(g).concat(" GB");
} else if (m>1) {
hrSize = isDouble(m) ? dec1.format(m).concat(" MB") : dec2.format(m).concat(" MB");
} else if (k>1) {
hrSize = isDouble(k) ? dec1.format(k).concat(" KB") : dec2.format(k).concat(" KB");
} else {
hrSize = isDouble(b) ? dec1.format(b).concat(" B") : dec2.format(b).concat(" B");
}
return hrSize;
}
You are performing integer division
. So the result of division is also integer
. And fractional part is truncated.
so, 1245 / 1024 = 1
Change your division to floating point division
: -
double m = size/1024.0;
double g = size/1048576.0;
double t = size/1073741824.0;
Also, your comparison is faulty. You should do the comparison with 1
.
if (m > 1), if (t > 1), if (g > 1)
Ideally I would change your comparison to: -
if (t > 1) {
hrSize = dec.format(t).concat("TB");
} else if (g > 1) {
hrSize = dec.format(g).concat("GB");
} else if (m > 1) {
hrSize = dec.format(m).concat("MB");
} else {
hrSize = dec.format(size).concat("KB");
}
You need to compare with the higher unit first, and then move to the lower one.