Как преобразовать размер байта в человекочитаемый формат в Java?


556

Как преобразовать размер байта в человекочитаемый формат в Java? Например, 1024 должно стать «1 Кб», а 1024 * 1024 должно стать «1 Мб».

Мне надоело писать этот метод для каждого проекта. Есть ли в Apache Commons статические методы для этого?


32
Если вы используете стандартные единицы измерения, 1024 должно стать «1 КБ», а 1024 * 1024 - «1 МБ». en.wikipedia.org/wiki/Binary_prefix
Паскаль Куок

@Pascal: должно быть несколько функций или опция для указания базы и единицы измерения.
Аарон Дигулла


3
@Pascal Cuoq: Спасибо за ссылку. Я не осознавал, пока не прочитал, что здесь, в ЕС, мы обязаны использовать правильные префиксы по закону.
JeremyP

2
@DerMike Вы упомянули, что «Пока такая библиотека не существует». Теперь это стало правдой. :-) stackoverflow.com/questions/3758606/…
Кристиан Эскен

Ответы:


1310

Интересный факт: оригинальный фрагмент, размещенный здесь, был самым скопированным фрагментом Java всех времен в Stack Overflow, и он был ошибочным. Это было исправлено, но стало грязно.

Полный текст этой статьи: Самый скопированный фрагмент StackOverflow за все время имеет недостатки!

Источник: Форматирование размера байта в удобочитаемый формат | Programming.Guide

SI (1 k = 1000)

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

Двоичный (1 K = 1024)

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

Пример вывода:

                              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)

12
Я предпочитаю 1,0 КБ. Тогда ясно, сколько значимых цифр влечет за собой результат. (Это также похоже на поведение, например, duкоманды в Linux.)
aioobe

19
Я думаю, что каждый должен отметить, что в вашем проекте заказчик хочет видеть значения в базе 2 (с разделением на 1024), но с общим префиксом. Не KiB, MiB, GiB и т. Д. Используйте для этого KB, MB, GB, TB.
Борис

27
@Borys Использование «KB» для обозначения «1024 байта» неверно. Не делай этого.
эндолит

8
Читатели узнают это. Лучше что-то, с чем они не знакомы и могут научиться этому, чем иметь что-то не так. При написании КБ пользователь, который знаком с ним, ожидает 1000, а незнакомый пользователь - 1024.
kap

16
Ответ переписан полностью. Многие из приведенных выше комментариев устарели.
Aioobe

305

FileUtils.byteCountToDisplaySize(long size)будет работать, если ваш проект может зависеть от org.apache.commons.io.

JavaDoc для этого метода


18
У меня уже есть commons-io в моем проекте, но в итоге я использовал код aioobe из-за поведения округления (см. Ссылку на JavaDoc)
Iravanchi

3
Есть ли утилита для выполнения обратной операции. Получение байтов из числа читаемых человеком байтов?
arunmoezhi

6
К сожалению, эта функция не учитывает локали; например, на французском языке они всегда называют байты «октетами», поэтому, если вы собираетесь отобразить файл размером 100 КБ для французского пользователя, правильная метка будет 100 Ko.
Такро

@Tacroy Вы можете получить вывод октетов с помощью UnitFormatter в библиотеке triava. Вы можете передать любую единицу в байтах, ваттах или октетах. Пример, слегка измененный по сравнению с примерами в github.com/trivago/triava : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1.13 ko" Больше примеров в: stackoverflow.com/questions/3758606/…
Кристиан

5
это округляет до ближайшего гб, когда> 1 гб, что означает, что точность, которую вы получаете от него, варьируется
tksfz

180

Используйте Android встроенный класс

Для Android есть класс Formatter . Всего одна строка кода, и все готово.

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

Это как formatFileSize(), но пытается генерировать более короткие числа (показывая меньше десятичных знаков).

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

Форматирует размер контента в байтах, килобайтах, мегабайтах и ​​т. Д.


12
должен быть лучшим ответом для Android окончательно. Никаких дополнительных библиотек не требуется. +1
Дитер

11
Я ненавижу тот факт, что вы должны пройти Context.
Джаред Берроуз

4
Должно быть лучшим ответом для ANDROID окончательно.
Шридутт Котари

5
Вы передаете в контексте, так что он переводится в текущую локаль пользователя. В противном случае это не было бы очень полезной функцией.
phreakhead

7
Я использовал принятый ответ, прежде чем я знаю это. Следует отметить, что в Build.VERSION_CODES.N и более ранних версиях вместо этого используются степени 1024, с KB = 1024 байта, MB = 1 048 576 байтов и т. Д. Что касается O, префиксы используются в их стандартных значениях в системе SI. , кБ = 1000 байт, МБ = 1 000 000 байт и т. д.
HendraWD

57

Мы можем полностью избежать использования медленных Math.pow()и Math.log()методов без ущерба для простоты, поскольку коэффициент между единицами (например, B, KB, MB и т. Д.) Равен 1024, что составляет 2 ^ 10. У Longкласса есть удобный numberOfLeadingZeros()метод, который мы можем использовать, чтобы указать, в какую единицу входит значение размера.

Ключевой момент: единицы измерения размера имеют расстояние в 10 бит (1024 = 2 ^ 10), что означает позицию старшего 1 бита - или, другими словами, число старших нулей - отличается на 10 (байт = КБ * 1024, КБ = МБ * 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));
}

24

Я недавно задавал тот же вопрос:

Формат файла размера как МБ, ГБ и т. Д.

Пока нет готового ответа, я могу жить с решением:

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

Тестовый код:

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

Изменить: я открыл проблему, запрашивая эту функцию для Google Guava . Возможно, кто-то захочет поддержать это.


2
Почему 0 неверный размер файла?
aioobe

@aioobe это было в моем случае использования (отображение размера загруженного файла), но, возможно, это не универсально
Шон Патрик Флойд

Если вы измените последнюю строку, чтобы вернуть NumberFormat.getFormat ("#, ## 0. #"). Format (result) + "" + unit; это работает и в GWT! Спасибо за это, это все еще не в Гуаве.
Том

9

Это модифицированная версия ответа 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);
}

Это немного смешанные результаты для передачи параметра Locale только для символов разделителя, но затем не следует также локализовать модуль для учета языков, которые также используют другой символ для байтов, например французский.
Nzall

@Nzall Вы имеете в виду октет? Википедия заявляет, что это больше не распространено. Иначе, у вас есть ссылка?
Кристиан Штремпфер

7

Если вы используете Android, вы можете просто использовать android.text.format.Formatter.formatFileSize () .

Альтернативно, вот решение, основанное на этом популярном посте :

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

Или в Котлине:

/**
 * 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()
}

Похоже, у вас в цикле for произошла ошибка. Я думаю так должно быть unitsCountи нет unitsCount-1.
aioobe

@aioobe, но это означает, что цикл может остановиться, когда i == unitsCount, что означает i == 6, что означает, что «charAt» не удастся ...
Android

if(result<unit) break;пойдет до этого. Не беспокойся. (Если вы проверите его, вы заметите, что можете полностью пропустить условие цикла for.)
aioobe

@aioobe Правильно, это из-за предположения (которое является правильным), что я обрабатываю «длинный» тип переменной. Кроме того, это основано на предположении, что единицы будут по крайней мере тем, что я написал. Если вы используете меньше единиц, это приведет к странным результатам (предпочтительнее, чем значения меньше 1, а не значения больше 1000).
Android-разработчик

@aioobe Правильно. Я починю это. Кстати, ваш алгоритм также может дать странный результат. попробуйте указать в качестве аргумента "999999, true". он покажет «1000,0 кБ», поэтому он округлен, но когда люди видят его, они могут задаться вопросом: почему он не может показать 1 МБ, так как 1000 КБ = 1 МБ ... Как вы думаете, как это должно быть обработано? Это из-за String.format, но я не уверен, как это должно быть исправлено.
разработчик Android

6

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

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

Мне это нравится, потому что за ним легко следовать и легко понять.
Джошуа Пинтер

6

Единицы байтов позволяют вам сделать это так:

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-Unit, которая позволяет вам делать это так:

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

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

3

Теперь доступна одна библиотека, которая содержит форматирование модулей. Я добавил его в триаву библиотеку , так как единственная другая существующая библиотека, похоже, для Android.

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

UnitFormatter.formatAsUnit(1126, UnitSystem.SI, "B");
// = "1.13kB"
UnitFormatter.formatAsUnit(2094, UnitSystem.IEC, "B");
// = "2.04KiB"

Печать точных килограмм, мегаполисов (здесь с W = Watt):

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

2

Я знаю, что уже поздно обновлять этот пост! но я повеселился с этим:

Создать интерфейс:

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

Создать класс StorageUnits:

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

2

В случайном случае это экономит кому-то немного времени, или, может быть, просто для развлечения, вот версия Go. Для простоты я включил только двоичный регистр вывода.

func sizeOf(bytes int64) string {
    const unit = 1024
    if bytes < unit {
        return fmt.Sprintf("%d B", bytes)
    }

    fb := float64(bytes)
    exp := int(math.Log(fb) / math.Log(unit))
    pre := "KMGTPE"[exp-1]
    div := math.Pow(unit, float64(exp))
    return fmt.Sprintf("%.1f %ciB", fb / div, pre)
}

1
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 ("Размер файла в правильном формате:" + байты + "" + fileSizeUnits [индекс]); sizeToReturn = String.valueOf (bytes) + "" + fileSizeUnits [index]; вернуть sizeToReturn; }


1

Вот эквивалент 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);
    }

Технически говоря, если мы придерживаемся единиц СИ, эта процедура работает для любого регулярного использования чисел. Есть много других хороших ответов от экспертов. Предположим, вы выполняете привязку данных к числам в виде сетки, поэтому стоит проверить из них подпрограммы, оптимизированные по производительности.

PS: опубликовано, потому что этот вопрос / ответ был на первом месте в поиске Google, пока я работаю над проектом C #.


1

Вы можете использовать StringUtils «S TraditionalBinarPrefix:

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

1

немного староват, но ... org.springframework.util.unit.DataSize может подойти к этому требованию хотя бы для расчета, тогда подойдет простой декоратор


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

Этот ответ, хотя он и работает, является дополнением к предыдущему ответу в этой теме от @ user601806: stackoverflow.com/a/4888400/3987745 Чтобы этот ответ работал, вам потребуется Apache Commons IO ( commons.apache.org/proper/ Commons-IO ) зависимость.
Эдвард Кихот

0

Вы пробовали JSR 363 ? Его модули расширения модулей, такие как Unicode CLDR (в GitHub: uom-systems ), сделают все это за вас.

Вы можете использовать MetricPrefixвключенные в каждую реализацию или BinaryPrefix(сравнимые с некоторыми из приведенных выше примеров), и если вы, например, живете и работаете в Индии или соседней стране IndianPrefix(также в общем модуле uom-systems), вы можете использовать и форматировать «Crore» Bytes "или" Lakh Bytes "тоже.


0

Может быть, вы можете использовать этот код (в C #):

        long Kb = 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 size.ToString() + " byte";
        if (size < Mb) return (size / Kb).ToString("###.##") + " Kb.";
        if (size < Gb) return (size / Mb).ToString("###.##") + " Mb.";
        if (size < Tb) return (size / Gb).ToString("###.##") + " Gb.";
        if (size < Pb) return (size / Tb).ToString("###.##") + " Tb.";
        if (size < Eb) return (size / Pb).ToString("###.##") + " Pb.";
        if (size >= Eb) return (size / Eb).ToString("###.##") + " Eb.";

        return "invalid size";

0
public String humanReadable(long size) {
    long limit = 10 * 1024;
    long limit2 = limit * 2 - 1;
    String negative = "";
    if(size < 0) {
        negative = "-";
        size = Math.abs(size);
    }

    if(size < limit) {
        return String.format("%s%s bytes", negative, size);
    } else {
        size = Math.round((double) size / 1024);
        if (size < limit2) {
            return String.format("%s%s kB", negative, size);
        } else {
            size = Math.round((double)size / 1024);
            if (size < limit2) {
                return String.format("%s%s MB", negative, size);
            } else {
                size = Math.round((double)size / 1024);
                if (size < limit2) {
                    return String.format("%s%s GB", negative, size);
                } else {
                    size = Math.round((double)size / 1024);
                        return String.format("%s%s TB", negative, size);
                }
            }
        }
    }
}

0

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

getFullMemoryUnit(): Total: [123 MB], Max: [1 GB, 773 MB, 512 KB], Free: [120 MB, 409 KB, 304 Bytes]
public static String getFullMemoryUnit(long unit) {
    long BYTE = 1024, KB = BYTE, MB = KB * KB, GB = MB * KB, TB = GB * KB;
    long KILO_BYTE, MEGA_BYTE = 0, GIGA_BYTE = 0, TERA_BYTE = 0;
    unit = Math.abs(unit);
    StringBuffer buffer = new StringBuffer();
    if ( unit / TB > 0 ) {
        TERA_BYTE = (int) (unit / TB);
        buffer.append(TERA_BYTE+" TB");
        unit -= TERA_BYTE * TB;
    }
    if ( unit / GB > 0 ) {
        GIGA_BYTE = (int) (unit / GB);
        if (TERA_BYTE != 0) buffer.append(", ");
        buffer.append(GIGA_BYTE+" GB");
        unit %= GB;
    }
    if ( unit / MB > 0 ) {
        MEGA_BYTE = (int) (unit / MB);
        if (GIGA_BYTE != 0) buffer.append(", ");
        buffer.append(MEGA_BYTE+" MB");
        unit %= MB;
    }
    if ( unit / KB > 0 ) {
        KILO_BYTE = (int) (unit / KB);
        if (MEGA_BYTE != 0) buffer.append(", ");
        buffer.append(KILO_BYTE+" KB");
        unit %= KB;
    }
    if ( unit > 0 ) buffer.append(", "+unit+" Bytes");
    return buffer.toString();
}

Я только что изменил код facebookarchive -StringUtils чтобы получить следующий формат. Тот же формат, который вы получите при использовании apache.hadoop-StringUtils

getMemoryUnit(): Total: [123.0 MB], Max: [1.8 GB], Free: [120.4 MB]
public static String getMemoryUnit(long bytes) {
    DecimalFormat oneDecimal = new DecimalFormat("0.0");
    float BYTE = 1024.0f, KB = BYTE, MB = KB * KB, GB = MB * KB, TB = GB * KB;
    long absNumber = Math.abs(bytes);
    double result = bytes;
    String suffix = " Bytes";
    if (absNumber < MB) {
        result = bytes / KB;
        suffix = " KB";
    } else if (absNumber < GB) {
        result = bytes / MB;
        suffix = " MB";
    } else if (absNumber < TB) {
        result = bytes / GB;
        suffix = " GB";
    }
    return oneDecimal.format(result) + suffix;
}

Пример использования вышеперечисленных методов:

public static void main(String[] args) {
    Runtime runtime = Runtime.getRuntime();
    int availableProcessors = runtime.availableProcessors();

    long heapSize = Runtime.getRuntime().totalMemory(); 
    long heapMaxSize = Runtime.getRuntime().maxMemory();
    long heapFreeSize = Runtime.getRuntime().freeMemory();

    System.out.format("Total: [%s], Max: [%s], Free: [%s]\n", heapSize, heapMaxSize, heapFreeSize);
    System.out.format("getMemoryUnit(): Total: [%s], Max: [%s], Free: [%s]\n",
            getMemoryUnit(heapSize), getMemoryUnit(heapMaxSize), getMemoryUnit(heapFreeSize));
    System.out.format("getFullMemoryUnit(): Total: [%s], Max: [%s], Free: [%s]\n",
            getFullMemoryUnit(heapSize), getFullMemoryUnit(heapMaxSize), getFullMemoryUnit(heapFreeSize));
}

Байты, чтобы получить выше формат

Total: [128974848], Max: [1884815360], Free: [126248240]

Для отображения времени в удобочитаемом формате используйте эту функцию millisToShortDHMS(long duration).


0

вот преобразование из @aioobe, преобразованное в kotlin

/**
 * https://stackoverflow.com/a/3758880/1006741
 */
fun Long.humanReadableByteCountBinary(): String {
    val b = when (this) {
        Long.MIN_VALUE -> Long.MAX_VALUE
        else -> abs(this)
    }
    return when {
        b < 1024L -> "$this B"
        b <= 0xfffccccccccccccL shr 40 -> "%.1f KiB".format(Locale.UK, this / 1024.0)
        b <= 0xfffccccccccccccL shr 30 -> "%.1f MiB".format(Locale.UK, this / 1048576.0)
        b <= 0xfffccccccccccccL shr 20 -> "%.1f GiB".format(Locale.UK, this / 1.073741824E9)
        b <= 0xfffccccccccccccL shr 10 -> "%.1f TiB".format(Locale.UK, this / 1.099511627776E12)
        b <= 0xfffccccccccccccL -> "%.1f PiB".format(Locale.UK, (this shr 10) / 1.099511627776E12)
        else -> "%.1f EiB".format(Locale.UK, (this shr 20) / 1.099511627776E12)
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.