web-dev-qa-db-fra.com

Comment éviter les exceptions de format de nombre en Java?

Dans le cadre de mon développement quotidien d'applications Web, il est souvent nécessaire de prendre certaines entrées numériques de l'utilisateur. 

Transmettez ensuite ce numéro à l'entrée qui peut être un service ou une couche DAO de l'application. 

À un moment donné, puisque c'est un nombre (entier ou flottant), nous devons le convertir en Integer, comme indiqué dans l'extrait de code suivant.

String cost = request.getParameter("cost");

if (cost !=null && !"".equals(cost) ){
    Integer intCost = Integer.parseInt(cost);
    List<Book> books = bookService . findBooksCheaperThan(intCost);  
}

Ici, dans le cas ci-dessus, je dois vérifier si l'entrée n'est pas nulle ou s'il n'y a pas d'entrée (vierge) ou s'il existe parfois une possibilité d'une entrée non numérique, par ex. bla, test etc.

Quel est le meilleur moyen de gérer de telles situations?

14
ashishjmeshram

Attrapez simplement votre exception et effectuez la gestion appropriée des exceptions: 

if (cost !=null && !"".equals(cost) ){
        try {
           Integer intCost = Integer.parseInt(cost);
           List<Book> books = bookService . findBooksCheaperThan(intCost);  
        } catch (NumberFormatException e) {
           System.out.println("This is not a number");
           System.out.println(e.getMessage());
        }
    }
27
RoflcoptrException

Comme toujours, les Communes de Jakarta ont au moins une partie de la réponse:

NumberUtils.isNumber ()

Ceci peut être utilisé pour vérifier si une chaîne donnée est un nombre. Vous devez encore choisir quoi faire au cas où votre chaîne ne serait pas un numéro ...

4
Guillaume

Les exceptions dans les versions récentes de Java ne sont pas assez chères pour rendre leur évitement important. Utilisez le bloc try/catch suggéré par les utilisateurs; Si vous détectez l'exception au début du processus (c'est-à-dire juste après que l'utilisateur l'ait entrée), le problème ne se posera pas plus tard dans le processus (car ce sera le bon type de toute façon).

Les exceptions étaient beaucoup plus chères qu'aujourd'hui; n'optimisez pas les performances tant que vous ne savez pas que les exceptions posent réellement un problème (et elles ne le feront pas, ici.)

2
Joseph Ottinger

Je suggère de faire 2 choses:

  • valider l'entrée côté client avant de la transmettre à la servlet
  • attraper l'exception et afficher un message d'erreur dans l'interface utilisateur, comme mentionné par Tobiask. Ce cas ne devrait normalement pas se produire, mais ne faites jamais confiance à vos clients. ;-)
1
Puce
public class Main {
    public static void main(String[] args) {

        String number;

        while(true){

            try{
                number = JOptionPane.showInputDialog(null);

                if( Main.isNumber(number) )
                    break;

            }catch(NumberFormatException e){
                System.out.println(e.getMessage());
            }

        }

        System.out.println("Your number is " + number);

    }

    public static boolean isNumber(Object o){
        boolean isNumber = true;

        for( byte b : o.toString().getBytes() ){
            char c = (char)b;
            if(!Character.isDigit(c))
                isNumber = false;
        }

        return isNumber;
    }

}
1
user3162218

une possibilité: attraper l'exception et afficher un message d'erreur dans l'interface utilisateur. 

edit: ajoute un auditeur au champ dans l'interface graphique et vérifie les entrées de l'utilisateur là aussi, avec cette solution le cas d'exception devrait être très rare ...

1
Tobias

Documentation pour la méthode de Apache Commons Lang ( à partir d’ici ):

Vérifie si la chaîne est un numéro Java valide.

Les nombres valides incluent les caractères hexadécimaux marqués du qualificatif 0x, la notation scientifique et les chiffres marqués d’un qualificatif de type (par exemple, 123L).

Null et String vide renverra false.

Paramètres:

`str` - the `String` to check

Résultats:

`true` if the string is a correctly formatted number

isNumber from Java.org.Apache.commons.lang3.math.NumberUtils :

public static boolean isNumber(final String str) {
    if (StringUtils.isEmpty(str)) {
        return false;
    }
    final char[] chars = str.toCharArray();
    int sz = chars.length;
    boolean hasExp = false;
    boolean hasDecPoint = false;
    boolean allowSigns = false;
    boolean foundDigit = false;
    // deal with any possible sign up front
    final int start = (chars[0] == '-') ? 1 : 0;
    if (sz > start + 1 && chars[start] == '0' && chars[start + 1] == 'x') {
        int i = start + 2;
        if (i == sz) {
            return false; // str == "0x"
        }
        // checking hex (it can't be anything else)
        for (; i < chars.length; i++) {
            if ((chars[i] < '0' || chars[i] > '9')
                && (chars[i] < 'a' || chars[i] > 'f')
                && (chars[i] < 'A' || chars[i] > 'F')) {
                return false;
            }
        }
        return true;
    }
    sz--; // don't want to loop to the last char, check it afterwords
          // for type qualifiers
    int i = start;
    // loop to the next to last char or to the last char if we need another digit to
    // make a valid number (e.g. chars[0..5] = "1234E")
    while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
        if (chars[i] >= '0' && chars[i] <= '9') {
            foundDigit = true;
            allowSigns = false;

        } else if (chars[i] == '.') {
            if (hasDecPoint || hasExp) {
                // two decimal points or dec in exponent   
                return false;
            }
            hasDecPoint = true;
        } else if (chars[i] == 'e' || chars[i] == 'E') {
            // we've already taken care of hex.
            if (hasExp) {
                // two E's
                return false;
            }
            if (!foundDigit) {
                return false;
            }
            hasExp = true;
            allowSigns = true;
        } else if (chars[i] == '+' || chars[i] == '-') {
            if (!allowSigns) {
                return false;
            }
            allowSigns = false;
            foundDigit = false; // we need a digit after the E
        } else {
            return false;
        }
        i++;
    }
    if (i < chars.length) {
        if (chars[i] >= '0' && chars[i] <= '9') {
            // no type qualifier, OK
            return true;
        }
        if (chars[i] == 'e' || chars[i] == 'E') {
            // can't have an E at the last byte
            return false;
        }
        if (chars[i] == '.') {
            if (hasDecPoint || hasExp) {
                // two decimal points or dec in exponent
                return false;
            }
            // single trailing decimal point after non-exponent is ok
            return foundDigit;
        }
        if (!allowSigns
            && (chars[i] == 'd'
                || chars[i] == 'D'
                || chars[i] == 'f'
                || chars[i] == 'F')) {
            return foundDigit;
        }
        if (chars[i] == 'l'
            || chars[i] == 'L') {
            // not allowing L with an exponent or decimal point
            return foundDigit && !hasExp && !hasDecPoint;
        }
        // last character is illegal
        return false;
    }
    // allowSigns is true iff the val ends in 'E'
    // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
    return !allowSigns && foundDigit;
}

[le code est sous la version 2 de la licence Apache]

1
A T

Essayez de convertir Prize en format décimal ...

import Java.math.BigDecimal;
import Java.math.RoundingMode;

public class Bigdecimal {
    public static boolean isEmpty (String st) {
        return st == null || st.length() < 1; 
    }
    public static BigDecimal bigDecimalFormat(String Preis){        
        //MathContext   mi = new MathContext(2);
        BigDecimal bd = new BigDecimal(0.00);

                         bd = new BigDecimal(Preis);


            return bd.setScale(2, RoundingMode.HALF_UP);

        }
    public static void main(String[] args) {
        String cost = "12.12";
        if (!isEmpty(cost) ){
            try {
               BigDecimal intCost = bigDecimalFormat(cost);
               System.out.println(intCost);
               List<Book> books = bookService.findBooksCheaperThan(intCost);  
            } catch (NumberFormatException e) {
               System.out.println("This is not a number");
               System.out.println(e.getMessage());
            }
        }

}
}
0

Déterminer si une chaîne est Int ou Float et représenter dans un format plus long.

Entier

 String  cost=Long.MAX_VALUE+"";
  if (isNumeric (cost))    // returns false for non numeric
  {  
      BigInteger bi  = new BigInteger(cost);

  }

public static boolean isNumeric(String str) 
{ 
  NumberFormat formatter = NumberFormat.getInstance(); 
  ParsePosition pos = new ParsePosition(0); 
  formatter.parse(str, pos); 
  return str.length() == pos.getIndex(); 
} 
0
Dead Programmer

Vous pouvez éviter les tentatives désagréables d’essai/capture ou regex en utilisant la classe Scanner:

String input = "123";
Scanner sc = new Scanner(input);
if (sc.hasNextInt())
    System.out.println("an int: " + sc.nextInt());
else {
    //handle the bad input
}
0
nairbv