132 votes

Formater la taille du fichier en MB, GB, etc.

J'ai besoin d'afficher la taille d'un fichier sous forme de chaîne de caractères en utilisant des unités sensibles.

Par exemple,

1L ==> "1 B";
1024L ==> "1 KB";
2537253L ==> "2.3 MB"

etc.

J'ai trouvé cette réponse précédente ce que je n'ai pas trouvé satisfaisant.

J'ai trouvé ma propre solution qui présente les mêmes inconvénients :

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 String.format("%.1f %s", Double.valueOf(result), unit);
}

Le principal problème est ma connaissance limitée du format décimal et / ou du format String.format. J'aimerais que 1024L, 1025L, etc. soient convertis en 1 KB plutôt que 1.0 KB .

Donc, deux possibilités :

  1. Je préférerais une bonne solution prête à l'emploi dans une bibliothèque publique telle que Apache Commons o Google Guava .
  2. Si ce n'est pas le cas, comment puis-je me débarrasser de la partie '.0' (sans avoir recours au remplacement de chaînes de caractères et aux expressions rationnelles, je peux le faire moi-même) ?

0 votes

Vous aimerez peut-être [la réponse ici] [1] car il s'agit d'une solution vraiment efficace, qui respecte les normes SI. [1] : stackoverflow.com/questions/3758606/

0 votes

Je suis au courant de cette question (et de la réponse acceptée), j'ai également a posté une réponse ici en faisant référence à cette question. Cette question est venue en premier, cependant, et n'a pas reçu une si bonne réponse.

0 votes

C'est ma faute, je n'avais pas remarqué que c'était vous qui aviez posté le lien vers cette question sur l'autre. C'est en fait comme ça que je suis arrivé ici.

397voto

Mr Ed Points 2068
public static String readableFileSize(long size) {
    if(size <= 0) return "0";
    final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
    int digitGroups = (int) (Math.log10(size)/Math.log10(1024));
    return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}

Cela fonctionnera jusqu'à 1000 TB.... et le programme est court !

0 votes

Cela devrait être la réponse "correcte" car elle tient compte de l'unité.

3 votes

D'accord, ce devrait être la bonne réponse. Regardez aquí pour un rendement encore meilleur.

4 votes

Final String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "EB" } ; // maintenant cela fonctionne jusqu'à Long.MAX_VALUE !

8voto

Robert Watkins Points 319

Vous aurez probablement plus de chance avec java.text.DecimalFormat . Ce code devrait probablement faire l'affaire (j'improvise...).

new DecimalFormat("#,##0.#").format(value) + " " + unit

0 votes

Fonctionne-t-il comme prévu ?

0 votes

Bizarrement, après dix ans, je ne suis pas retourné en arrière pour tester cela. Essayez vous-même et voyez...

6voto

Hugo Points 3276

Vous pourriez aimer la réponse ici car il s'agit d'une solution vraiment efficace, qui respecte les normes du SI.

6voto

R Jobs Points 19

C'est surprenant pour moi, mais un algorithme basé sur des boucles est environ 10% plus rapide.

public static String toNumInUnits(long bytes) {
    int u = 0;
    for ( ; bytes > 1024*1024; bytes >>= 10) {
        u++;
    }
    if (bytes > 1024)
        u++;
    return String.format("%.1f %cB", bytes/1024f, " kMGTPE".charAt(u));
}

4 votes

Tout est basé sur la boucle au fond.

0 votes

@Evgeni Sergeev : Que voulez-vous dire ? Pouvez-vous préciser ?

0 votes

Avertissement : cela ne fonctionne pas pour les octets <= 1024 (le résultat est toujours 0.0 B). Vous devez ajouter if (bytes <= 1024) { return String.format("%.1f B", (float) bytes); } au début de la méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X