Converting KB to MB, GB, TB dynamically

梦想与她 提交于 2019-11-30 12:13:27

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.

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

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

The problem is that you're using integer division. Change your code to:

double m = size/1024.0;
double g = size/1048576.0;
double t = size/1073741824.0;

In your original code, double m = size/1024 would divide the integer size by 1024, truncate the result to an integer, and only then convert it to double. This is why the fractional part was getting lost.

You are performing integer division,

i.e., 31/15 will result in 2, not 2.whatever

just append the number with D or d which denotes it as a double and you will be fine

double m = size/1024D;
double g = size/1048576D;
double t = size/1073741824D;

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
String[] fileSizeUnits = {"bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
public String calculateProperFileSize(double bytes){
    String sizeToReturn = "";// = FileUtils.byteCountToDisplaySize(bytes), unit = ""; 
    int index = 0;
    for(index = 0; index < fileSizeUnits.length; index++){
        if(bytes < 1024){
            break;
        }
        bytes = bytes / 1024;
    }
    System.out.println("Systematic file size: " + bytes + " " + fileSizeUnits[index]);
    sizeToReturn = String.valueOf(bytes) + " " + fileSizeUnits[index];
    return sizeToReturn;
}

Just add more file units (if any missing), and you will see unit size upto that unit (if your file has that much length)

My basic version (you CAN define some constants instead of computing POW all the time):

public static String GetFolderSizeHuman(long aBytes)
{
  if (aBytes < 1024 * 1024) 
    return aBytes + " KB";
  else if (aBytes < Math.pow(2, 20) * 1024)
    return (int) aBytes / Math.pow(2, 20) + " MB";
  else if (aBytes < Math.pow(2, 30) * 1024 )
    return kGbTbFormatter.format(aBytes / Math.pow(2, 30)) + " GB";
  else if (aBytes < Math.pow(2, 40) * 1024)
    return kGbTbFormatter.format(aBytes / Math.pow(2, 40)) + " TB";

  else return "N/A (1TB?)";
}
X09

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;
    }
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 = kb / 1024;
        double tb = kb / 1024;
        if(size < 1024) {
            s = size + " Bytes";
        } else if(size >= 1024 && size < (1024 * 1024)) {
            s =  String.format("%.2f", kb) + " KB";
        } else if(size >= (1024 * 1024) && size < (1024 * 1024 * 1024)) {
            s = String.format("%.2f", mb) + " MB";
        } else if(size >= (1024 * 1024 * 1024) && size < (1024 * 1024 * 1024 * 1024)) {
            s = String.format("%.2f", gb) + " GB";
        } else if(size >= (1024 * 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!