web-dev-qa-db-fra.com

Formater la taille du fichier en Mo, Go, etc.

Je dois afficher une taille de fichier sous forme de chaîne à l'aide d'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

Je suis venu avec ma propre solution qui a des lacunes similaires:

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 problème principal est ma connaissance limitée de Decimalformat et/ou String.format. Je voudrais 1024L, 1025L etc pour mapper à 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 ou Google Guava.
  2. S'il n'y en a pas, quelqu'un peut-il me montrer comment se débarrasser de la partie '.0' (sans avoir recours au remplacement de chaîne ni à la regex, je peux le faire moi-même)
114
Sean Patrick Floyd
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 To .... et le programme est court!

357
Mr Ed

Vous aurez probablement plus de chance avec Java.text.DecimalFormat. Ce code devrait probablement le faire (juste le faire voler ...)

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

8
Robert Watkins

Étonnamment pour moi, mais l'algorithme basé sur les 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));
}
2
R Jobs