13

Using DecimalFormat gives no parse exception when using this kind of number:

123hello

which is obviously not really a number, and converts to 123.0 value. How can I avoid this kind of behaviour?

As a side note hello123 does give an exception, which is correct.

Thanks, Marcel

marcel
  • 302
  • 1
  • 7

3 Answers3

9

To do exact parsing, you can use

public Number parse(String text,
                ParsePosition pos)

Initialize pos to 0 and when its finished it will give you the index after the last character that was used.

You can then compare this against string length to make sure the parse was accurate.

http://download.oracle.com/javase/1.4.2/docs/api/java/text/DecimalFormat.html#parse%28java.lang.String,%20java.text.ParsePosition%29

Kal
  • 23,894
  • 7
  • 58
  • 61
  • 1
    Only a pitty that the API does not allow to do something like this: decimalFormat.setStrict(true) (strict meaning not allowing 123hello as number). The point is that you cannot always control the call to parse yourself. Other libraries might use the format object. Many thanks for the reply! – marcel Jul 07 '11 at 09:22
2

Expanding on @Kal's answer, here's a utility method which you can use with any formatter to do "strict" parsing (uses apache commons StringUtils):

public static Object parseStrict(Format fmt, String value)
    throws ParseException
{
    ParsePosition pos = new ParsePosition(0);
    Object result = fmt.parseObject(value, pos);
    if(pos.getIndex() < value.length()) {
        // ignore trailing blanks
        String trailing = value.substring(pos.getIndex());
        if(!StringUtils.isBlank(trailing)) {
            throw new ParseException("Failed parsing '" + value + "' due to extra trailing character(s) '" +
                                     trailing + "'", pos.getIndex());
        }
    }
    return result;
}
jtahlborn
  • 50,774
  • 5
  • 71
  • 112
0

You can verify it is numeric using a RegEx:

String input = "123hello";
double d = parseDouble(input); // Runtime Error

public double parseDouble(String input, DecimalFormat format) throws NumberFormatException
{
    if (input.equals("-") || input.equals("-."))
       throw NumberFormatException.forInputString(input);
    if (!input.matches("\\-?[0-9]*(\\.[0-9]*)?"))
       throw NumberFormatException.forInputString(input);

    // From here, we are sure it is numeric.
    return format.parse(intput, new ParsePosition(0));
}
Martijn Courteaux
  • 63,780
  • 43
  • 187
  • 279
  • 2
    Your code doesn't bring anything other than Double.parseDouble("123hello"). And The point of DecimalFormat is to parse internationalized numbers. 123 456,78 is a valid decimal number in the French locale. – JB Nizet Jul 06 '11 at 17:51
  • @JB: indeed, I wanted to be to fast :D – Martijn Courteaux Jul 06 '11 at 19:43