Преобразование КБ в МБ, ГБ, ТБ динамически

public String size(int size){
    String hrSize = "";
    int k = size;
    double m = size/1024;
    double g = size/1048576;
    double t = size/1073741824;

    DecimalFormat dec = new DecimalFormat("0.00");

    if (k>0)
    {

        hrSize = dec.format(k).concat("KB");

    }
    if (m>0)
    {

        hrSize = dec.format(m).concat("MB");
    }
    if (g>0)
    {

        hrSize = dec.format(g).concat("GB");
    }
    if (t>0)
    {

        hrSize = dec.format(t).concat("TB");
    }

    return hrSize;
    }

Это метод, который должен возвращать размер в ГБ,МБ, КБ или ТБ. Входное значение находится в КБ. например, результат для 1245 должен быть как 1.21 MB, но я получаю 1.00 MB.

9 ответов


выполняется integer division. Таким образом, результат деления также integer. А дробная часть усечена.

so, 1245 / 1024 = 1

измените деление на floating point division: -

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

кроме того, ваше сравнение неисправен. Вы должны сделать сравнение с 1.

if (m > 1), if (t > 1), if (g > 1)

в идеале я бы изменил ваше сравнение на: -

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

сначала вам нужно сравнить с более высокой единицей, а затем перейти к нижней.


модифицированная версия. Только формат вызовов один раз. Включает "Байты".

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

Я люблю этот:

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

проблема в том, что вы используете целочисленное деление. Измените код на:

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

в исходном коде double m = size/1024 разделит целое число size by 1024, усечь результат в целое число и только затем преобразовать его в double. Вот почему частичная часть терялась.


вы выполняете целочисленное деление,

т. е. 31/15 приведет к 2, а не 2.все

просто добавьте номер с D или d который обозначает его как двойной, и вы будете в порядке

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

его не легко получить это право. Рохит Джайн упомянул целочисленную операцию. Также округление может быть проблемой, так как всегда округление может быть нежелательным. Я бы посоветовал пойти на решение, как в triava библиотека.

оно может форматировать номера с произвольной точностью, в 3 различных системах (SI, IEC, JEDEC) и различных вариантах выхода. Вот несколько примеров кода из модульные тесты triava:

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

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

просто добавьте больше файловых единиц (если они отсутствуют), и вы увидите размер единицы до этой единицы (если ваш файл имеет такую длину)


моя базовая версия (вы можете определить некоторые константы вместо вычисления POW все время):

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

bickster это работает вполне нормально, но проблема в том, что он возвращает результаты, такие как 45.00 Bytes и 12.00 KB. На мой взгляд, последние десятичные цифры должны быть удалены, если они являются нулями. Так вместо 45.00 Bytes и 12.00 KB вы получаете 45 B и 12 KB (извещение Bytes было изменено на B. Это просто для единообразия, так как у нас есть КБ, МБ и т. д., а не килобайты, мегабайты и т. д.).

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

вышеуказанный метод просто проверяет если значение имеет нули в виде десятичных цифр.

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