Number Formats


We already mentioned how number and currency formatting is highly locale dependent. The Java programming language supplies a collection of formatter objects that can format and parse numeric values in the java.text class. You go through the following steps to format a number for a particular locale.

  1. Get the locale object, as described in the preceding section.

  2. Use a "factory method" to obtain a formatter object.

  3. Use the formatter object for formatting and parsing.

The factory methods are static methods of the NumberFormat class that take a Locale argument. There are three factory methods: getNumberInstance, getCurrencyInstance, and getPercentInstance. These methods return objects that can format and parse numbers, currency amounts, and percentages, respectively. For example, here is how you can format a currency value in German.

 Locale loc = new Locale("de", "DE"); NumberFormat currFmt = NumberFormat.getCurrencyInstance(loc); double amt = 123456.78; System.out.println(currFmt.format(amt)); 

This code prints

 123.456,78 DM 

Note that the currency symbol is DM and that it is placed at the end of the string. Also, note the reversal of decimal points and decimal commas.

Conversely, to read in a number that was entered or stored with the conventions of a certain locale, use the parse method. For example, the following code parses the value that the user typed into a text field. The parse method can deal with decimal points and commas, as well as digits in other languages.

 TextField inputField; . . . NumberFormat fmt = NumberFormat.getNumberInstance(); // get number formatter for default locale Number input = fmt.parse(inputField.getText().trim()); double x = input.doubleValue(); 

The return type of parse is the abstract type Number. The returned object is either a Double or a Long wrapper object, depending on whether the parsed number was a floating-point number. If you don't care about the distinction, you can simply use the doubleValue method of the Number class to retrieve the wrapped number.

CAUTION

Objects of type Number are not automatically unboxedyou cannot simply assign a Number object to a primitive type. Instead, use the doubleValue or intValue method.


If the text for the number is not in the correct form, the method throws a ParseException. For example, leading whitespace in the string is not allowed. (Call trim to remove it.) However, any characters that follow the number in the string are simply ignored, so no exception is thrown.

Note that the classes returned by the getXxxInstance factory methods are not actually of type NumberFormat. The NumberFormat type is an abstract class, and the actual formatters belong to one of its subclasses. The factory methods merely know how to locate the object that belongs to a particular locale.

You can get a list of the currently supported locales with the static getAvailableLocales method. That method returns an array of the locales for which number formatter objects can be obtained.

The sample program for this section lets you experiment with number formatters (see Figure 10-1). The combo box at the top of the figure contains all locales with number formatters. You can choose between number, currency, and percentage formatters. Each time you make another choice, the number in the text field is reformatted. If you go through a few locales, then you get a good impression of how many ways a number or currency value can be formatted. You can also type a different number and click the Parse button to call the parse method, which tries to parse what you entered. If your input is successfully parsed, then it is passed to format and the result is displayed. If parsing fails, then a "Parse error" message is displayed in the text field.

Figure 10-1. The NumberFormatTest program


The code, shown in Example 10-1, is fairly straightforward. In the constructor, we call NumberFormat.getAvailableLocales. For each locale, we call geTDisplayName, and we fill a combo box with the strings that the geTDisplayName method returns. (The strings are not sorted; we tackle this issue with a custom combo box later in this chapter.) Whenever the user selects another locale or clicks on one of the radio buttons, we create a new formatter object and update the text field. When the user clicks on the Parse button, we call the parse method to do the actual parsing, based on the locale selected.

Example 10-1. NumberFormatTest.java
   1. import java.awt.*;   2. import java.awt.event.*;   3. import java.text.*;   4. import java.util.*;   5. import javax.swing.*;   6.   7. /**   8.    This program demonstrates formatting numbers under   9.    various locales.  10. */  11. public class NumberFormatTest  12. {  13.    public static void main(String[] args)  14.    {  15.       JFrame frame = new NumberFormatFrame();  16.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  17.       frame.setVisible(true);  18.    }  19. }  20.  21. /**  22.    This frame contains radio buttons to select a number format,  23.    a combo box to pick a locale, a text field to display  24.    a formatted number, and a button to parse the text field  25.    contents.  26. */  27. class NumberFormatFrame extends JFrame  28. {  29.    public NumberFormatFrame()  30.    {  31.       setTitle("NumberFormatTest");  32.       setLayout(new GridBagLayout());  33.  34.       ActionListener listener = new  35.          ActionListener()  36.          {  37.             public void actionPerformed(ActionEvent event) { updateDisplay(); }  38.          };  39.  40.       JPanel p = new JPanel();  41.       addRadioButton(p, numberRadioButton, rbGroup, listener);  42.       addRadioButton(p, currencyRadioButton, rbGroup, listener);  43.       addRadioButton(p, percentRadioButton, rbGroup, listener);  44.  45.       add(new JLabel("Locale:"), new GBC(0, 0).setAnchor(GBC.EAST));  46.       add(p, new GBC(1, 1));  47.       add(parseButton, new GBC(0, 2).setInsets(2));  48.       add(localeCombo, new GBC(1, 0).setAnchor(GBC.WEST));  49.       add(numberText, new GBC(1, 2).setFill(GBC.HORIZONTAL));  50.       locales = NumberFormat.getAvailableLocales();  51.       for (Locale loc : locales) localeCombo.addItem(loc.getDisplayName());  52.       localeCombo.setSelectedItem(Locale.getDefault().getDisplayName());  53.       currentNumber = 123456.78;  54.       updateDisplay();  55.  56.       localeCombo.addActionListener(listener);  57.  58.       parseButton.addActionListener(new  59.          ActionListener()  60.          {  61.             public void actionPerformed(ActionEvent event)  62.             {  63.                String s = numberText.getText().trim();  64.                try  65.                {  66.                   Number n = currentNumberFormat.parse(s);  67.                   if (n != null)  68.                   {  69.                      currentNumber = n.doubleValue();  70.                      updateDisplay();  71.                   }  72.                   else  73.                   {  74.                      numberText.setText("Parse error: " + s);  75.                   }  76.                }  77.                catch (ParseException e)  78.                {  79.                   numberText.setText("Parse error: " + s);  80.                }  81.             }  82.          });  83.       pack();  84.    }  85.  86.    /**  87.       Adds a radio button to a container.  88.       @param p the container into which to place the button  89.       @param b the button  90.       @param g the button group  91.       @param listener the button listener  92.    */  93.    public void addRadioButton(Container p, JRadioButton b,  94.       ButtonGroup g, ActionListener listener)  95.    {  96.       b.setSelected(g.getButtonCount() == 0);  97.       b.addActionListener(listener);  98.       g.add(b);  99.       p.add(b); 100.    } 101. 102.    /** 103.       Updates the display and formats the number according 104.       to the user settings. 105.    */ 106.    public void updateDisplay() 107.    { 108.       Locale currentLocale = locales[localeCombo.getSelectedIndex()]; 109.       currentNumberFormat = null; 110.       if (numberRadioButton.isSelected()) 111.          currentNumberFormat = NumberFormat.getNumberInstance(currentLocale); 112.       else if (currencyRadioButton.isSelected()) 113.          currentNumberFormat = NumberFormat.getCurrencyInstance(currentLocale); 114.       else if (percentRadioButton.isSelected()) 115.          currentNumberFormat = NumberFormat.getPercentInstance(currentLocale); 116.       String n = currentNumberFormat.format(currentNumber); 117.       numberText.setText(n); 118.    } 119. 120.    private Locale[] locales; 121.    private double currentNumber; 122.    private JComboBox localeCombo = new JComboBox(); 123.    private JButton parseButton = new JButton("Parse"); 124.    private JTextField numberText = new JTextField(30); 125.    private JRadioButton numberRadioButton = new JRadioButton("Number"); 126.    private JRadioButton currencyRadioButton = new JRadioButton("Currency"); 127.    private JRadioButton percentRadioButton = new JRadioButton("Percent"); 128.    private ButtonGroup rbGroup = new ButtonGroup(); 129.    private NumberFormat currentNumberFormat; 130. } 


 java.text.NumberFormat 1.1 

  • static Locale[] getAvailableLocales()

    returns an array of Locale objects for which NumberFormat formatters are available.

  • static NumberFormat getNumberInstance()

  • static NumberFormat getNumberInstance(Locale l)

  • static NumberFormat getCurrencyInstance()

  • static NumberFormat getCurrencyInstance(Locale l)

  • static NumberFormat getPercentInstance()

  • static NumberFormat getPercentInstance(Locale l)

    return a formatter for numbers, currency amounts, or percentage values for the current locale or for the given locale.

  • String format(double x)

  • String format(long x)

    return the string resulting from formatting the given floating-point number or integer.

  • Number parse(String s)

    parses the given string and returns the number value, as a Double if the input string described a floating-point number, and as a Long otherwise. The beginning of the string must contain a number; no leading whitespace is allowed. The number can be followed by other characters, which are ignored. Throws ParseException if parsing was not successful.

  • void setParseIntegerOnly(boolean b)

  • boolean isParseIntegerOnly()

    set or get a flag to indicate whether this formatter should parse only integer values.

  • void setGroupingUsed(boolean b)

  • boolean isGroupingUsed()

    set or get a flag to indicate whether this formatter emits and recognizes decimal separators (such as 100,000).

  • void setMinimumIntegerDigits(int n)

  • int getMinimumIntegerDigits()

  • void setMaximumIntegerDigits(int n)

  • int getMaximumIntegerDigits()

  • void setMinimumFractionDigits(int n)

  • int getMinimumFractionDigits()

  • void setMaximumFractionDigits(int n)

  • int getMaximumFractionDigits()

    set or get the maximum or minimum number of digits allowed in the integer or fractional part of a number.

Currencies

To format a currency value, you can use the NumberFormat.getCurrencyInstance method. However, that method is not very flexibleit returns a formatter for a single currency. Suppose you prepare an invoice for an American customer in which some amounts are in dollars, and others in Euros. You can't just use two formatters

 NumberFormat dollarFormatter = NumberFormat.getCurrencyInstance(Locale.US); NumberFormat euroFormatter = NumberFormat.getCurrencyInstance(Locale.GERMANY); 

Your invoice would look very strange, with some values formatted like $100,000 and others like 100.000 . (Note that the Euro value uses a decimal point, not a comma.)

Instead, use the Currency class to control the currency that is used by the formatters. You get a Currency object by passing a currency identifier to the static Currency.getInstance method. Then call the setCurrency method for each formatter. Here is how you would set up the Euro formatter for your American customer:

 NumberFormat euroFormatter = NumberFormat.getCurrencyInstance(Locale.US); euroFormatter.setCurrency(Currency.getInstance("EUR")); 

The currency identifiers are defined by ISO 4217see http://en.wikipedia.org/wiki/ISO_4217 for a list. Table 10-3 provides a partial list. (The official maintainer of the standard charges £70 for this informationsee http://www.bsi-global.com/Technical+Information/Publications/_Publications/tig90.xalter.)


 java.util.Currency 1.4 

Table 10-3. Common Currency Identifiers

US Dollar

USD

Euro

EUR

British Pound

GBP

Japanese Yen

JPY

Chinese Renminbi (Yuan)

CNY

Indian Rupee

INR

Russian Ruble

RUB


  • static Currency getInstance(String currencyCode)

  • static Currency getInstance(Locale locale)

    return the Currency instance for the given ISO 4217 currency code or the country of the given locale.

  • String toString()

  • String getCurrencyCode()

    get the ISO 4217 currency code of this currency.

  • String getSymbol()

  • String getSymbol(Locale locale)

    get the formatting symbol of this currency for the default locale or the given locale. For example, the symbol for USD may be "$" or "US$", depending on the locale.

  • int getDefaultFractionDigits()

    gets the default number of fraction digits of this currency.



    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net