Comment convertir la taille des octets en format lisible par l'homme en java?


Comment convertir la taille des octets en format lisible par l'homme en Java? Comme 1024 devrait devenir " 1 Ko "et 1024*1024 devrait devenir"1 Mo".

J'en ai un peu marre d'écrire cette méthode utilitaire pour chaque projet. Existe-il des méthodes statiques dans Apache Commons pour cela?

Author: unwind, 2010-09-21

20 answers

Voici mon aller à elle (pas de boucles et gère 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

 1112
Author: aioobe, 2016-10-29 03:58:01

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

JavaDoc de cette méthode

 254
Author: user601806, 2016-06-07 13:27:35

Utiliser la classe intégrée Android

Pour Android il existe une classe Formateur. 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, kilo-octets, mégaoctets, etc.

 127
Author: AZ_, 2015-09-15 13:59:54

Nous pouvons complètement éviter d'utiliser les méthodes lentes Math.pow() et Math.log() sans sacrifier la simplicité puisque le facteur entre les unités (par exemple B, KB, MB etc.) est 1024 qui est 2^10. La classe Long a une méthode pratique numberOfLeadingZeros() que nous pouvons utiliser pour dire dans 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 que la position du bit le plus élevé - ou en d'autres termes le nombre de zéros principaux - diffèrent de 10 (Octets = KB*1024, KO=MO*1024 etc.).

Corrélation entre le nombre de zéros principaux 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
Author: icza, 2018-03-03 08:50:45

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

Formater la taille du fichier en Mo, Go 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 mes paramètres régionaux allemands):

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 le soutenir.

 22
Author: Sean Patrick Floyd, 2017-05-23 12:26:42

Ceci est une version modifiée de la réponse aioobe.

Modifications:

  • 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
Author: Christian Strempfer, 2017-05-23 12:10:54

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

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

  /**
   * 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
Author: android developer, 2017-05-23 11:33:25

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
Author: Lars Bohl, 2011-05-18 14:53:35
    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
Author: XXX, 2014-04-09 15:26:53
  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
Author: Sujith Manjavana, 2015-06-13 18:48:12

Il y a maintenant une bibliothèque disponible qui contient le formatage des unités. Je l'ai ajouté à la bibliothèque triava , car la seule autre bibliothèque existante semble être celle 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 des tests unitaires triava :

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

Impression de kilo exact, de méga valeurs (ici avec W = Watt):

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

Vous pouvez passer un DecimalFormat à personnaliser la sortie:

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

Pour les opérations arbitraires sur des 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
 3
Author: Christian Esken, 2016-07-15 07:31:00

Les unités d'octets vous permettent de le faire comme ceci:

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

, j'ai écrit une autre bibliothèque appelée stockage-unités, ce qui permet de faire comme ceci:

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

Si vous voulez forcer une certaine unité, faites ceci:

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

Assert.assertEquals("1024.00 KiB", formattedUnit9);
Assert.assertEquals("1.00 MB", formattedUnit10);
 2
Author: Sebastian Hoß, 2016-08-17 21:30:51

Je sais qu'il est trop tard pour mettre à jour ce post! mais je me suis amusé avec ça:

Créer une interface:

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

Créer une classe 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.#");
}
}

Appelez-le:

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

Sortie:

21.4kB
2GB
 2
Author: Ahmad AlMughrabi, 2017-07-30 13:11:13
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;
    }

Ajoutez simplement plus d'unités de fichier (le cas échéant), et vous verrez la taille de l'unité jusqu'à cette unité (si votre fichier a autant de longueur) Système.hors.println ("Taille du fichier au format approprié:" + octets + "" + fileSizeUnits[index]); sizeToReturn = Chaîne.valueOf (octets) + "" + fileSizeUnits[index]; retour sizeToReturn; }

 1
Author: Vishwajit R. Shinde, 2015-01-20 13:16:30

Voici l'équivalent C#. net pour la réponse de consensus correcte Java ci-dessus. (il y en a un autre ci-dessous qui a des codes plus courts)

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

Techniquement parlant, si nous nous en tenons aux unités SI, cette routine fonctionne pour toute utilisation régulière des nombres. Il y a beaucoup d'autres bonnes réponses d'experts. Supposons que vous fassiez une liaison de données de nombres sur gridviews, cela vaut la peine de vérifier les routines optimisées pour les performances.

PS: Posté parce que cette question / réponse est apparue en haut sur la recherche Google pendant que je fais un projet C#.

 1
Author: Chan Fun Chiat, 2016-03-31 04:14:15
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);
 0
Author: Mano Chella, 2014-04-08 10:15:16

Avez-vous essayé JSR 363? Ses modules d'extension unitaires comme Unicode CLDR (dans GitHub: uom-systems) font tout cela pour vous.

Vous pouvez utiliser MetricPrefix inclus dans chaque implémentation ou BinaryPrefix (comparable à certains des exemples ci-dessus) et si vous vivez et travaillez par exemple en Inde ou dans un pays voisin, IndianPrefix (également dans le module commun des systèmes uom) vous permet d'utiliser et de formater "Crore Octets" ou "Lakh Octets", aussi.

 0
Author: Werner Keil, 2016-10-24 08:24:44

Vous pouvez utiliser StringUtils’s TraditionalBinarPrefix:

public static String humanReadableInt(long number) {
    return TraditionalBinaryPrefix.long2String(number,””,1);
}
 0
Author: Joseph K, 2017-10-31 14:18:50

Peut-être que vous pouvez utiliser ce code(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";
 0
Author: Jacons Morais, 2018-07-11 01:47:02

Dans le hasard, cela fait gagner un peu de temps à quelqu'un, ou peut-être juste pour s'amuser, voici une version Go. Pour plus de simplicité, je n'ai inclus que le cas de sortie binaire.

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)
}
 0
Author: Rick-777, 2018-10-04 15:21:33