DecimalFormat converts numbers with non-digits
Asked Answered
F

3

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

Florafloral answered 6/7, 2011 at 17:28 Comment(1)
Look at this #4325497Spraddle
N
10

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

Needleful answered 6/7, 2011 at 17:36 Comment(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!Florafloral
A
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;
}
Afraid answered 6/7, 2011 at 20:4 Comment(0)
D
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));
}
Dialectology answered 6/7, 2011 at 17:39 Comment(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.Heideheidegger
@JB: indeed, I wanted to be to fast :DDialectology

© 2022 - 2025 — McMap. All rights reserved.