Question Comment convertir la taille en octets dans un format lisible par l'homme en Java?


Comment convertir la taille en octets dans un format lisible par l'homme en Java? Comme 1024 devrait devenir "1 Kb" et 1024 * 1024 devrait devenir "1 Mb".

Je suis assez malade d'écrire cette méthode utilitaire pour chaque projet. Existe-t-il des méthodes statiques dans Apache Commons pour cela?


441
2017-09-21 08:42


origine


Réponses:


Voici mon aller à elle (pas de boucles et gère à la fois les unités SI et les unités binaires):

public static String humanReadableByteCount(long bytes, boolean si) {
    int unit = si ? 1000 : 1024;
    if (bytes < unit) return bytes + " B";
    int exp = (int) (Math.log(bytes) / Math.log(unit));
    String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
    return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}

Exemple de sortie:

                              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)

Article connexe: Java: formatage de la taille des octets au format lisible par l'homme


1100
2017-09-21 09:22



FileUtils.byteCountToDisplaySize(long size) fonctionnerait si votre projet peut dépendre de org.apache.commons.io.

JavaDoc pour cette méthode


248
2018-02-03 15:57



Utiliser la classe intégrée Android

Pour Android il y a une classe Formatter. Juste un comme du code et vous avez terminé.

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

C'est comme formatFileSize(), mais en essayant de générer des nombres plus courts (montrant moins de décimales).

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

Formate une taille de contenu sous la forme d'octets, de kilo-octets, de méga-octets, etc.


123
2017-10-22 07:38



Nous pouvons éviter complètement d'utiliser le lent Math.pow() et Math.log() méthodes sans sacrifier la simplicité puisque le facteur entre les unités (par exemple B, KB, MB, etc.) est de 1024, soit 2 ^ 10. le Long classe a un pratique numberOfLeadingZeros() méthode que nous pouvons utiliser pour dire quelle unité la valeur de taille tombe.

Point clé: Les unités de taille ont une distance de 10 bits (1024 = 2 ^ 10), ce qui signifie la position du bit 1 le plus élevé - ou, en d'autres nombre de zéros principaux - diffèrent de 10 (octets = KB * 1024, KB = MB * 1024, etc.).

Corrélation entre le nombre de zéros et l'unité de taille:

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

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

37
2017-07-17 14:08



J'ai posé la même question récemment:

Format de fichier au format MB, GB, etc.

Bien qu'il n'y ait pas de réponse prête à l'emploi, je peux vivre avec la solution:

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

Code de test:

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

Sortie (sur mon site allemand):

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

Edit: J'ai ouvert un Problème demandant cette fonctionnalité pour Google Guava. Peut-être que quelqu'un voudrait l'appuyer.


21
2017-09-21 08:49



Ceci est une version modifiée de La réponse d'Aioobe.

Changements:

  • Locale paramètre, car certaines langues utilisent . et d'autres , comme point décimal.
  • code lisible par l'homme

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

7
2017-11-17 09:18



Si vous utilisez Android, vous pouvez simplement utiliser Formatter.formatFileSize () .

Alternativey, voici une solution basée sur ce post populaire :

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

7
2018-05-03 09:38




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
2018-05-18 14:53



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

5
2018-04-09 15:26



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

3
2018-06-13 18:48



Il y a maintenant une bibliothèque disponible qui contient le formatage d'unité. Je l'ai ajouté à la triava bibliothèque, car la seule autre bibliothèque existante semble être une pour Android.

Il peut formater des nombres avec une précision arbitraire, dans 3 systèmes différents (SI, IEC, JEDEC) et diverses options de sortie. Voici quelques exemples de code du tests unitaires triava:

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

Impression exacte du kilo, méga-valeur (ici avec W = Watt):

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

Vous pouvez passer un DecimalFormat pour personnaliser la sortie:

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

Pour les opérations arbitraires sur les valeurs kilo ou méga, vous pouvez les diviser en composants:

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

2
2017-07-15 07:31