How to parse numbers more strict than what NumberFormat does in Java?
-
29-10-2019 - |
Question
I'm validating user input from a form.
I parse the input with NumberFormat
, but it is evil and allow almost anything. Is there any way to parse number more strict?
E.g. I would like to not allow these three inputs, for an integer, but Numberformat
allow all of them:
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setParseIntegerOnly(true);
Number numberA = nf.parse("99.731"); // 99 (not what the user expect)
Number numberB = nf.parse("99s.231"); // 99 (invalid)
Number numberC = nf.parse("9g9"); // 9 (invalid)
System.out.println(numberA.toString());
System.out.println(numberB.toString());
System.out.println(numberC.toString());
No correct solution
OTHER TIPS
Maybe this helps:
String value = "number_to_be_parsed".trim();
NumberFormat formatter = NumberFormat.getNumberInstance();
ParsePosition pos = new ParsePosition(0);
Number parsed = formatter.parse(value, pos);
if (pos.getIndex() != value.length() || pos.getErrorIndex() != -1) {
throw new RuntimeException("my error description");
}
(Thanks to Strict number parsing at mynetgear.net)
There are many ways to do that:
- regex - check if it
matches("\\d+")
- with
javax.validation
-@Digits(fraction=0, integer=5)
- apache commons
IntegerValidator
Integer.parseInt(String)
will throw a NumberFormatException on all of your examples. I'm not sure if that's what you're looking for, but it's definitely "more strict."
Use DecimalFormat with a format pattern string.
Take a look at DecimalFormat that is a subclass of NumberFormat http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
DecimalFormat myFormatter = new DecimalFormat("###.###");
I wouldn't use java's number format routine, especially with the locale settings if you worry about validation.
Locale numberLocale = new Locale(“es”,”ES");
NumberFormat nf = NumberFormat.getInstance(numberLocale);
ParsePosition pos = new ParsePosition(0);
Number test = nf.parse("0.2", pos);
You would expect there to be an issue here, but no.. test is equal to 2 and pos has an index of 3 and error index of -1.
I gave up on writing my own validation class, and went with NEBULA WIDGETS FormattedText
It was written over the SWT widget API, but you can easily adapt the NumberFormatter class