Parsing Values Using Patterns
An instance of the MessageFormat class can be used both for formatting and for parsing of values. The class provides the parse() methods for parsing text. We will primarily use the one-argument method shown below to demonstrate parsing with the MessageFormat class.
Object[] parse(String source) throws ParseException
Object[] parse(String source, ParsePosition position)
The first method parses text from the beginning of the string source to return an Object array with the parsed values.
The second method parses from the position in the string source where the parsing should start.
Both methods may not use the entire text of the given string source.
The parse() methods return an Object array with the parsed values, which means that the parsed values must be extracted from the array and cast to the appropriate type in order to compute with them. The cast to the appropriate type must be done safely—typically by determining the type with the instanceof operator before applying the cast.
As the one-argument parse() method throws a checked ParseException when an error occurs under parsing, the code snippets in this subsection must be executed in a context that handles this exception.
The round trip of formatting values and then parsing the formatted result to obtain the same values back is illustrated below. It should not come as a surprise that this round trip always works, as demonstrated by the code below. We see that the argument of type double that was formatted and the value of type double that was parsed according to the pattern at (1) are equal.
String pattern = “foo {0,number,currency} bar”; // (1)
MessageFormat mfp = new MessageFormat(pattern, Locale.US);
Object[] arguments = new Object[] {10.99}; // [10.99]
String formattedResult = mfp.format(arguments); // “foo $10.99 bar”
Object[] parsedResult = mfp.parse(formattedResult); // [10.99]
System.out.println((double)arguments[0] == (double)parsedResult[0]); // true
A vanilla format element, {i}, in a pattern matches a string in the source, as no format type or style is specified for such a format element. The source at (3) matches the format element in the pattern at (2), as is evident from the parse result at (4).
String patternA = “{0}”; // (2)
MessageFormat mfpA = new MessageFormat(patternA, Locale.US);
Object[] parsedResultA = mfpA.parse(“One Two Three”); // (3)
System.out.println(parsedResultA[0] instanceof String); // true
System.out.println(Arrays.toString(parsedResultA)); // (4) [One Two Three]
Any text in a pattern must be matched verbatim in the source. Note how the text in the pattern at (5) is matched in the source at (6), with the string “2” being returned as the result of parsing.
String patternB = “One {0} Three”; // (5)
MessageFormat mfpB = new MessageFormat(patternB, Locale.US);
Object[] parsedResultB = mfpB.parse(“One 2 Three”); // (6)
System.out.println(parsedResultB[0].equals(“2”)); // true
System.out.println(Arrays.toString(parsedResultB)); // [2]
The code below illustrates that the parse() method may not use the entire text in the source, only what is necessary to declare a match. Parsing stops after the word Three in the source at (7) when a match for the pattern has been found in the source.
Object[] parsedResultC = mfpB.parse(“One 2 Three whatever”); // (7)
System.out.println(Arrays.toString(parsedResultC)); // [2]
In order for the parse to succeed, the source must contain text that is compatible with the pattern so that it can be parsed according to any type or style specified in the format elements defined in the pattern. At (8) below, the pattern contains two format elements that require an integer and a currency value specified according to the US locale. The source at (9) meets the requirements to match the pattern. The parse result shows that an int value and a double value were parsed.
String patternD = “foo {0,number,integer} {1,number,currency} bar”; // (8)
MessageFormat mfpD = new MessageFormat(patternD, Locale.US);
Object[] parsedResultD = mfpD.parse(“foo 2021 $64.99 bar”); // (9)
System.out.println(Arrays.toString(parsedResultD)); // [2021, 64.99]
We have seen earlier in this chapter that a nbsp is necessary in the source in order to parse certain currencies (p. 1119). That is also the case when parsing such currency values with the MessageFormat class, and is illustrated below for the Norwegian locale. Unless a nbsp is the delimiter between the currency symbol and the first digit of the amount, as shown at (10b), parsing will result in a checked Parse-Exception being thrown.
Locale locale = new Locale(“no”, “NO”);
String pattern1 = “foo {0,number,currency} bar”;
MessageFormat mfp1 = new MessageFormat(pattern1, locale);
// String parseSource = “foo kr 10,99 bar”; // (10a) ParseException
String parseSource = “foo kr\u00a010,99 bar”; // (10b) nbsp. OK.
Object[] parsedResults = mfp1.parse(parseSource);
if (parsedResults[0] instanceof Double dValue) {
System.out.println(dValue); // 10.99
}
Leave a Reply