¿Cómo convertir el tamaño de bytes en formato legible para humanos en Java?

556

¿Cómo convertir el tamaño de bytes en formato legible para humanos en Java? Como 1024 debería convertirse en "1 Kb" y 1024 * 1024 debería convertirse en "1 Mb".

Estoy harto de escribir este método de utilidad para cada proyecto. ¿Hay algún método estático en Apache Commons para esto?

Igor Mukhin
fuente
32
Si utiliza las unidades estandarizadas, 1024 debería convertirse en "1KiB" y 1024 * 1024 debería convertirse en "1MiB". en.wikipedia.org/wiki/Binary_prefix
Pascal Cuoq
@Pascal: debe haber varias funciones o una opción para especificar la base y la unidad.
Aaron Digulla
posible duplicado del tamaño del archivo de formato como MB, GB, etc.
Aaron Digulla
3
@Pascal Cuoq: Gracias por la referencia. No me di cuenta hasta que lo leí que aquí en la UE estamos obligados a usar los prefijos correctos por ley.
JeremyP
2
@DerMike Usted mencionó que "Hasta que tal biblioteca exista". Esto ahora se ha hecho realidad. :-) stackoverflow.com/questions/3758606/…
Christian Esken

Respuestas:

1310

Dato curioso: el fragmento original publicado aquí era el fragmento de Java más copiado de todos los tiempos en Stack Overflow, y tenía fallas. Se arregló pero se volvió desordenado.

Historia completa en este artículo: ¡ El fragmento de StackOverflow más copiado de todos los tiempos es defectuoso!

Fuente: Formato de tamaño de byte a formato legible para humanos | Programación Guía

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

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

Salida de ejemplo:

                              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)
aioobe
fuente
12
Prefiero 1.0 KB. Entonces está claro cuántas cifras significativas conlleva la producción. (Esto también parece ser el comportamiento de, por ejemplo, el ducomando en Linux.)
aioobe
19
Creo que todos deberían tener en cuenta que en su proyecto el cliente quiere ver los valores en la base 2 (divididos por 1024) pero con un prefijo común. No KiB, MiB, GiB, etc. Utilice KB, MB, GB, TB para ello.
Borys
27
@Borys Usar "KB" para significar "1024 bytes" es incorrecto. No hagas eso.
endolito
8
Los lectores lo aprenderán. Es mejor algo con lo que no están familiarizados y pueden aprenderlo que tener algo mal. Al escribir KB, un usuario que esté familiarizado con él esperará 1000 y un usuario que no esté familiarizado esperará 1024.
kap
16
Respuesta reescrita por completo. Muchos de los comentarios anteriores son obsoletos.
aioobe
305

FileUtils.byteCountToDisplaySize(long size)funcionaría si su proyecto puede depender org.apache.commons.io.

JavaDoc para este método

usuario601806
fuente
18
Ya tengo commons-io en mi proyecto, pero terminé usando el código de aioobe, debido al comportamiento de redondeo (vea el enlace para JavaDoc)
Iravanchi
3
¿Hay alguna utilidad para hacer la operación inversa? ¿Obtener el recuento de bytes del recuento de bytes legibles por humanos?
arunmoezhi
66
Lamentablemente, esta función no es compatible con la configuración regional; en francés, por ejemplo, siempre llaman bytes "octetos", por lo que si va a mostrar un archivo de 100 KB a un usuario francés, la etiqueta correcta sería 100 Ko.
Tacroy
@Tacroy Puede obtener salida de octetos con UnitFormatter en la biblioteca triava. Puede pasar cualquier unidad por bytes, vatios u octetos. Ejemplo, ligeramente modificado de los ejemplos en github.com/trivago/triava : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1.13 ko" Más ejemplos en: stackoverflow.com/questions/3758606/…
Christian Esken
55
esto se redondea al gb más cercano cuando> 1 gb, lo que significa que la precisión que obtienes varía
tksfz
180

Utilice la clase integrada de Android

Para Android hay un formateador de clase . Solo una línea de código y ya está.

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

Es como formatFileSize(), pero tratando de generar números más cortos (mostrando menos decimales).

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

Formatea un tamaño de contenido para que tenga la forma de bytes, kilobytes, megabytes, etc.

ARIZONA_
fuente
12
debería ser la mejor respuesta para Android definitivamente. No se necesitan bibliotecas adicionales. +1
dieter
11
Odio el hecho de que tengas que pasar Context.
Jared Burrows
44
Debería ser la mejor respuesta para Android definitivamente.
shridutt kothari
55
Pasa en contexto para que se traduzca a la configuración regional actual del usuario. De lo contrario, no sería una función muy útil.
phreakhead
77
Estaba usando la respuesta aceptada antes de saber esto. Solo para tener en cuenta, en Build.VERSION_CODES.N y anteriores, se utilizan potencias de 1024 en su lugar, con KB = 1024 bytes, MB = 1,048,576 bytes, etc. A partir de O, los prefijos se usan en sus significados estándar en el sistema SI , entonces kB = 1000 bytes, MB = 1,000,000 bytes, etc.
HendraWD
57

Podemos evitar por completo el uso de métodos lentos Math.pow()y Math.log()sin sacrificar la simplicidad ya que el factor entre las unidades (por ejemplo, B, KB, MB, etc.) es 1024, que es 2 ^ 10. La Longclase tiene un numberOfLeadingZeros()método útil que podemos usar para decir en qué unidad se encuentra el valor del tamaño.

Punto clave: las unidades de tamaño tienen una distancia de 10 bits (1024 = 2 ^ 10), lo que significa que la posición del 1 bit más alto, o en otras palabras, el número de ceros iniciales , difiere en 10 (Bytes = KB * 1024, KB = MB * 1024 etc.).

Correlación entre el número de ceros iniciales y la unidad de tamaño:

# of leading 0's   Size unit
-------------------------------
>53                B (Bytes)
>43                KB
>33                MB
>23                GB
>13                TB
>3                 PB
<=2                EB

El código final:

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));
}
icza
fuente
24

Hice la misma pregunta recientemente:

Tamaño del archivo de formato como MB, GB, etc.

Si bien no hay una respuesta lista para usar, puedo vivir con la solución:

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

Código de prueba:

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

Salida (en mi localidad alemana):

1 B
4,2 KB
41,4 MB
3,3 GB

Editar: he abierto un problema que solicita esta funcionalidad para Google Guava . Quizás a alguien le gustaría apoyarlo.

Sean Patrick Floyd
fuente
2
¿Por qué 0 es un tamaño de archivo no válido?
aioobe
@aioobe fue en mi caso de uso (que muestra el tamaño de un archivo cargado), pero podría decirse que no es universal
Sean Patrick Floyd el
Si cambia la última línea para devolver NumberFormat.getFormat ("#, ## 0. #"). Format (result) + "" + unit; ¡Funciona también en GWT! Gracias por esto, todavía no está en Guava.
tom
9

Esta es una versión modificada de la respuesta de aioobe .

Cambios:

  • Localeparámetro, porque algunos idiomas usan .y otros ,como punto decimal.
  • código legible por humanos

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);
}
Christian Strempfer
fuente
Es un poco un tanto confuso pasar un parámetro Locale solo para los símbolos separadores, pero luego no también localiza la unidad para tener en cuenta los idiomas que también usan un símbolo diferente para Bytes, como el francés.
Nzall
@Nzall ¿Te refieres al octeto? Wikipedia dice que ya no es común. De lo contrario, ¿tienes una referencia?
Christian Strempfer
7

Si usa Android, simplemente puede usar android.text.format.Formatter.formatFileSize () .

Alternativamente, aquí hay una solución basada en esta publicación popular :

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

O en 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()
}
desarrollador de Android
fuente
Parece que tiene un error off-by-one en su ciclo for. Creo que debería ser unitsCounty no unitsCount-1.
aioobe 05 de
@aioobe pero esto significa que el bucle se detendrá cuando i == unitsCount, lo que significa i == 6, que significa "charAt" se producirá un error ...
desarrollador de Android
if(result<unit) break;pateará antes de eso. Sin preocupaciones. (Si lo pruebas, se dará cuenta de que puede saltarse la condición de bucle completo.)
aioobe
@aioobe Correcto, eso se debe a la suposición (que es correcta) de que manejo el tipo de variable "largo". Además, se basa en el supuesto de que las unidades serán al menos lo que he escrito. Si usa menos unidades, producirá resultados extraños (preferirá valores inferiores a 1, en lugar de valores superiores a 1000).
Desarrollador de Android
@aioobe Correcto. Yo lo arreglare. Por cierto, su algoritmo también puede proporcionar un resultado extraño. intenta darle "999999, verdadero" como argumentos. mostrará "1000.0 kB", por lo que es redondeado, pero cuando la gente lo ve, pueden preguntarse: ¿por qué no puede mostrar 1 MB, ya que 1000 KB = 1 MB ... ¿Cómo crees que esto debería ser manejado? Se debe a String.format, pero no estoy seguro de cómo se debe solucionar.
Desarrollador de 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);
}
Lars Bohl
fuente
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";
        }
    }
Sujith Manjavana
fuente
Me gusta esto porque es fácil de seguir y fácil de entender.
Joshua Pinter
6

Byte Units te permite hacerlo así:

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

He escrito otra biblioteca llamada unidades de almacenamiento que le permite hacerlo así:

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

En caso de que quiera forzar una determinada unidad, haga esto:

String formattedUnit9 = StorageUnits.formatAsKibibyte(input2);
String formattedUnit10 = StorageUnits.formatAsCommonMegabyte(input2);

Assert.assertEquals("1024.00 KiB", formattedUnit9);
Assert.assertEquals("1.00 MB", formattedUnit10);
Sebastian Hoß
fuente
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 "???";
    }
XXX
fuente
3

Ahora hay una biblioteca disponible que contiene formato de unidad. Lo agregué a la triava biblioteca , ya que la única otra biblioteca existente parece ser una para Android.

Puede formatear números con precisión arbitraria, en 3 sistemas diferentes (SI, IEC, JEDEC) y varias opciones de salida. Aquí hay algunos ejemplos de código de las pruebas unitarias triava :

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

Imprimir kilo exactos, mega valores (aquí con W = Watt):

UnitFormatter.formatAsUnits(12_000_678, UnitSystem.SI, "W", ", ");
// = "12MW, 678W"

Puede pasar un DecimalFormat para personalizar la salida:

UnitFormatter.formatAsUnit(2085, UnitSystem.IEC, "B", new DecimalFormat("0.0000"));
// = "2.0361KiB"

Para operaciones arbitrarias en kilo o mega valores, puede dividirlos en componentes:

UnitComponent uc = new  UnitComponent(123_345_567_789L, UnitSystem.SI);
int kilos = uc.kilo(); // 567
int gigas = uc.giga(); // 123
Christian Esken
fuente
2

¡Sé que es demasiado tarde para actualizar esta publicación! pero me divertí un poco con esto:

Crea una interfaz:

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

Crear clase 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.#");
}
}

Llámalo:

class Main {
    public static void main(String... args) {
         System.out.println(StorageUnits.format(21885));
         System.out.println(StorageUnits.format(2188121545L));
    }
}

Salida:

21.4kB
2GB
Ahmad AlMughrabi
fuente
2

En el caso improbable, le ahorra a alguien un poco de tiempo, o tal vez solo por un poco de diversión, aquí hay una versión Go. Por simplicidad, solo he incluido el caso de salida binaria.

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)
}
Rick-777
fuente
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;
    }

Simplemente agregue más unidades de archivo (si falta alguna), y verá el tamaño de la unidad hasta esa unidad (si su archivo tiene tanta longitud) System.out.println ("Tamaño del archivo en el formato adecuado:" + bytes + "" + fileSizeUnits [índice]); sizeToReturn = String.valueOf (bytes) + "" + fileSizeUnits [index]; return sizeToReturn; }

Vishwajit R. Shinde
fuente
1

Aquí está el equivalente de C # .net para la respuesta de consenso correcta de Java anterior. (hay otro debajo que tiene códigos más cortos)

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

Técnicamente hablando, si nos atenemos a las unidades SI, esta rutina funciona para cualquier uso regular de números. Hay muchas otras buenas respuestas de expertos. Suponga que está vinculando datos de números en vistas de cuadrícula, vale la pena verificar las rutinas optimizadas de rendimiento de ellos.

PD: Publicado porque esta pregunta / respuesta apareció en la parte superior de la búsqueda de Google mientras estoy haciendo el proyecto C #.

Chan Fun Chiat
fuente
1

Puede utilizar StringUtils s’ TraditionalBinarPrefix:

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

un poco viejo pero, ... org.springframework.util.unit.DataSize podría adaptarse a este requisito al menos para el cálculo, entonces un simple decorador hará

Tama
fuente
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);
Mano Chella
fuente
Esta respuesta, mientras funciona, es un complemento de una respuesta anterior en este hilo de @ user601806: stackoverflow.com/a/4888400/3987745 Para que esta respuesta funcione, necesita Apache Commons IO ( commons.apache.org/proper/ commons-io ) dependencia.
Edward Quijote
0

¿Has probado JSR 363 ? Sus módulos de extensión de unidad como Unicode CLDR (en GitHub: uom-systems ) hacen todo eso por usted.

Puede usarlo MetricPrefixincluido en cada implementación o BinaryPrefix(comparable a algunos de los ejemplos anteriores) y si, por ejemplo, vive y trabaja en India o en un país cercano, IndianPrefix(también en el módulo común de uom-systems) le permite usar y formatear "Crore Bytes "o" Lakh Bytes ", también.

Werner Keil
fuente
0

Tal vez pueda usar este código (en 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";
Jacons Morais
fuente
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);
                }
            }
        }
    }
}
Samkov Max
fuente
0

Use la siguiente función para obtener información exacta, generada tomando la base del ATM_CashWithdrawlconcepto.

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

Acabo de modificar el código de facebookarchiveStringUtils para obtener el siguiente formato. El mismo formato que obtendrá cuando use 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;
}

Ejemplo de uso de los métodos anteriores:

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

Bytes para obtener el formato anterior

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

Para mostrar la hora en formato legible por humanos, use esta función millisToShortDHMS(long duration).

Yash
fuente
0

aquí está la conversión de @aioobe convertida a 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)
    }
}
Kibotu
fuente