Java-Convertir la Taille lisible par l'Homme en Octets


J'ai trouvé beaucoup d'informations sur la conversion d'informations brutes sur les octets dans un format lisible par l'homme, mais je dois faire le contraire, c'est-à-dire convertir la chaîne "1.6 Gb" en la valeur longue 1717990000. Existe-t-il un moyen intégré/bien défini de le faire, ou vais-je à peu près devoir rouler le mien?

[Edit]: Voici mon premier coup de couteau...

static class ByteFormat extends NumberFormat {
    @Override
    public StringBuffer format(double arg0, StringBuffer arg1, FieldPosition arg2) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public StringBuffer format(long arg0, StringBuffer arg1, FieldPosition arg2) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Number parse(String arg0, ParsePosition arg1) {
        return parse (arg0);
    }

    @Override
    public Number parse(String arg0) {
        int spaceNdx = arg0.indexOf(" ");
        double ret = Double.parseDouble(arg0.substring(0, spaceNdx));
        String unit = arg0.substring(spaceNdx + 1);
        int factor = 0;
        if (unit.equals("GB")) {
            factor = 1073741824;
        }
        else if (unit.equals("MB")) {
            factor = 1048576;
        }
        else if (unit.equals("KB")) {
            factor = 1024;
        }

        return ret * factor;
    }
}
Author: Dan Forbes, 2013-06-06

5 answers

Je n'ai jamais entendu parler d'une bibliothèque aussi connue, qui implémente de telles méthodes utilitaires d'analyse de texte. Mais votre solution semble être proche de la bonne implémentation.

Les deux seules choses que j'aimerais corriger dans votre code sont:

  1. Définir la méthode Number parse(String arg0) comme statique en raison de sa nature utilitaire

  2. Définissez factor s pour chaque type de définition de taille comme final static champs.

C'est-à-dire que ce sera comme celui-ci:

private final static long KB_FACTOR = 1024;
private final static long MB_FACTOR = 1024 * KB_FACTOR;
private final static long GB_FACTOR = 1024 * MB_FACTOR;

public static double parse(String arg0) {
    int spaceNdx = arg0.indexOf(" ");
    double ret = Double.parseDouble(arg0.substring(0, spaceNdx));
    switch (arg0.substring(spaceNdx + 1)) {
        case "GB":
            return ret * GB_FACTOR;
        case "MB":
            return ret * MB_FACTOR;
        case "KB":
            return ret * KB_FACTOR;
    }
    return -1;
}
 2
Author: Andremoniy, 2013-06-07 12:25:43

Une version révisée de la réponse d'Andremoniy qui distingue correctement entre kilo et kibi, etc.

private final static long KB_FACTOR = 1000;
private final static long KIB_FACTOR = 1024;
private final static long MB_FACTOR = 1000 * KB_FACTOR;
private final static long MIB_FACTOR = 1024 * KIB_FACTOR;
private final static long GB_FACTOR = 1000 * MB_FACTOR;
private final static long GIB_FACTOR = 1024 * MIB_FACTOR;

public static double parse(String arg0) {
    int spaceNdx = arg0.indexOf(" ");
    double ret = Double.parseDouble(arg0.substring(0, spaceNdx));
    switch (arg0.substring(spaceNdx + 1)) {
        case "GB":
            return ret * GB_FACTOR;
        case "GiB":
            return ret * GIB_FACTOR;
        case "MB":
            return ret * MB_FACTOR;
        case "MiB":
            return ret * MIB_FACTOR;
        case "KB":
            return ret * KB_FACTOR;
        case "KiB":
            return ret * KIB_FACTOR;
    }
    return -1;
}
 3
Author: gilbertpilz, 2015-10-22 19:08:55

Tout en une seule réponse, analyse en long:

public class SizeUtil {

    public static String units = "BKMGTPEZY";

    public static long parse(String arg0) {
        int spaceNdx = arg0.indexOf(" ");    
        double ret = Double.parseDouble(arg0.substring(0, spaceNdx));
        String unitString = arg0.substring(spaceNdx+1);
        int unitChar = unitString.charAt(0);
        int power = units.indexOf(unitChar);
        boolean isSi = unitString.indexOf('i')!=-1;
        int factor = 1024;
        if (isSi) 
        {
            factor = 1000;
        }

        return new Double(ret * Math.pow(factor, power)).longValue();
    }

    public static void main(String[] args) {
        System.out.println(parse("300.00 GiB")); // requires a space
        System.out.println(parse("300.00 GB"));
        System.out.println(parse("300.00 B"));
        System.out.println(parse("300 EB"));
    }
}
 3
Author: RobAu, 2018-01-19 22:30:16

Je sais que c'est beaucoup plus tard, mais je cherchais une fonction similaire qui prend en compte les préfixe SI ainsi. J'ai donc atterri en créant un moi-même et j'ai pensé que cela pourrait être utile pour d'autres personnes.

public static String units = "KMGTPE";

/**
 * Converts from human readable to byte format
 * @param number The number value of the amount to convert
 * @param unit The unit: B, KB, MB, GB, TB, PB, EB
 * @param si Si prefix
 * @return byte value
 */
public static double parse(double number, String unit, boolean si)
{
    String identifier = unit.substring(0, 1);
    int index = units.indexOf(identifier);
    //not already in bytes
    if (index!=-1)
    {
        for (int i = 0; i <= index; i++)
            number = number * (si ? 1000 : 1024);
    }
    return number;
}

Je suis sûr que cela est également possible avec la récursivité. Il était trop simple pour s'en préoccuper...

 2
Author: nbz, 2015-03-18 17:09:46

L'approche suivante peut également être utilisée et la rend générique, et ne dépend pas du caractère d'espace à analyser.

Merci à @RobAu pour l'indice ci-dessus. Ajout d'une nouvelle méthode pour obtenir l'index de la première lettre de la chaîne, et a changé la méthode d'analyse pour obtenir l'indice est basé sur cette nouvelle méthode. J'ai conservé la méthode d'analyse d'origine et ajouté une nouvelle méthode parseAny, afin que les résultats puissent être comparés. Espérons que cela aide quelqu'un.

Aussi, grâce à cette réponse pour la méthode indexOf - https://stackoverflow.com/a/11214786/6385674.

public class ConversionUtil {

    public static String units = "BKMGTPEZY";

    public static long parse(String arg0) {
        int spaceNdx = arg0.indexOf(" ");    
        double ret = Double.parseDouble(arg0.substring(0, spaceNdx));
        String unitString = arg0.substring(spaceNdx+1);
        int unitChar = unitString.charAt(0);
        int power = units.indexOf(unitChar);
        boolean isSi = unitString.indexOf('i')!=-1;
        int factor = 1024;
        if (isSi) 
        {
            factor = 1000;
        }

        return new Double(ret * Math.pow(factor, power)).longValue();
    }
    /** @return index of pattern in s or -1, if not found */
    public static int indexOf(Pattern pattern, String s) {
        Matcher matcher = pattern.matcher(s);
        return matcher.find() ? matcher.start() : -1;
    }    
    public static long parseAny(String arg0)
    {
        int index = indexOf(Pattern.compile("[A-Za-z]"), arg0);
        double ret = Double.parseDouble(arg0.substring(0, index));
        String unitString = arg0.substring(index);
        int unitChar = unitString.charAt(0);
        int power = units.indexOf(unitChar);
        boolean isSi = unitString.indexOf('i')!=-1;
        int factor = 1024;
        if (isSi) 
        {
            factor = 1000;
        }

        return new Double(ret * Math.pow(factor, power)).longValue();       

    }
    public static void main(String[] args) {
        System.out.println(parse("300.00 GiB")); // requires a space
        System.out.println(parse("300.00 GB"));
        System.out.println(parse("300.00 B"));        
        System.out.println(parse("300 EB"));
        System.out.println(parseAny("300.00 GiB"));
        System.out.println(parseAny("300M"));
    }
}
 0
Author: abhishek, 2018-09-29 05:59:37