Comment convertir la taille d'octet en format lisible par l'homme en java?

comment convertir la taille d'octet en format lisible par L'homme en Java? Comme 1024 devrait devenir "1 Kb" et 1024*1024 devrait devenir"1 Mb".

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

445
demandé sur unwind 2010-09-21 12:42:59

20 réponses

voici ce que je vais faire (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: le Formatage de la taille en octets de format lisible par l'homme

1112
répondu aioobe 2016-10-29 03:58:01

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

JavaDoc pour cette méthode

254
répondu user601806 2016-06-07 13:27:35

Utiliser Android builtin Classe

pour Android il ya une classe Formatter . Juste un, comme de 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 à être sous forme d'octets, kilo-octets, méga-octets, etc.

127
répondu 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 ce qui est 2^10. La classe Long a une méthode pratique numberOfLeadingZeros() que nous pouvons utiliser pour indiquer dans quelle unité la valeur de taille tombe.

Key point: les unités de taille ont une distance de 10 bits (1024=2^10) ce qui signifie la position du plus haut 1 bit - ou en d'autres termes le nombre de zéros de tête - diffèrent par 10 (octets=KB*1024, KB=MB*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
répondu icza 2018-03-03 08:50:45

j'ai posé la même Question récemment:

Format Taille du fichier en MB, GB etc

bien qu'il n'y ait pas de réponse évidente, 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 D'essai:

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));
    }
}
"151930920 de Sortie" (sur ma version allemande):

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

Edit: j'ai ouvert un numéro demandant ceci fonctionnalité pour Google Guava . Peut-être que quelqu'un voudrait le soutenir.

22
répondu Sean Patrick Floyd 2017-05-23 12:26:42

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

Changements:

  • Locale paramètre, parce que 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
répondu Christian Strempfer 2017-05-23 12:10:54

si vous utilisez Android, vous pouvez simplement utiliser formater.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
répondu 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
répondu 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
répondu 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
répondu Sujith Manjavana 2015-06-13 18:48:12

il y a maintenant une bibliothèque disponible qui contient des unités de formatage. 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 codes tirés des triava unit tests :

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

impression exact kilo, mega valeurs (ici avec W = Watt):

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

vous pouvez passer une forme décimale pour personnaliser la sortie:

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

pour des opérations arbitraires sur des valeurs de kilo ou mega, 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
répondu Christian Esken 2016-07-15 07:31:00

Byte Units vous permet 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 unités de stockage qui vous permet de le 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 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
répondu 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 la 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
répondu 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;
    }

il suffit d'ajouter plus d'unités de fichier (s'il en manque), et vous verrez la taille de l'unité jusqu'à cette unité (si votre fichier a cette longueur) Système.hors.println("taille du Fichier dans le format approprié:" + octets + "" + fileSizeUnits[index]); sizeToReturn = String.valueOf(octets) + "" + fileSizeUnits[index]; retour sizeToReturn; }

1
répondu Vishwajit R. Shinde 2015-01-20 13:16:30

Voici L'équivalent de C# .net pour la réponse de consensus correcte de Java ci-dessus. (Il ya un autre ci-dessous qui ont 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 de nombres. Il y a beaucoup d'autres bonnes réponses d'experts. Supposons que vous faites la saisie de données de nombres sur gridviews, sa valeur pour vérifier les performances optimisées routines à partir de ceux-ci.

PS: publié parce que ce question / réponse est venu en haut sur la recherche google alors que je fais c# projet.

1
répondu 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
répondu Mano Chella 2014-04-08 10:15:16

avez-vous essayé JSR 363 ? Ses modules d'extension d'unité 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 en Inde ou dans un pays voisin, IndianPrefix (également dans le module commun de uom-systems) vous permet d'utiliser et de formater "Crore Bytes" ou " Lakh Octets", trop.

0
répondu 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
répondu Joseph K 2017-10-31 14:18:50

peut-être Pouvez-vous 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
répondu Jacons Morais 2018-07-11 01:47:02

En dehors de la chance, il sauve quelqu'un un peu de temps, ou peut-être juste pour un peu de plaisir, voici une Go version. Pour simplifier, j'ai seulement inclus 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
répondu Rick-777 2018-10-04 15:21:33