epubjs
Version:
Render ePub documents in the browser, across many devices
156 lines (151 loc) • 25.1 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Formatting with the java.text Package</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Formatting with the java.text Package"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-10-SECT-6"/>Formatting with the java.text Package</h1></div></div></div><p><a id="idx10528" class="indexterm"/> <a id="idx10578" class="indexterm"/>The <code class="literal">java.text</code> package
includes, among other things, a set of classes designed for generating and
parsing string representations of objects. In this section, we’ll talk
about three classes: <a id="I_indexterm10_id731170" class="indexterm"/><code class="literal">NumberFormat</code>, <a id="I_indexterm10_id731181" class="indexterm"/><code class="literal">ChoiceFormat</code>, and
<a id="I_indexterm10_id731192" class="indexterm"/><code class="literal">MessageFormat</code>. <a class="xref" href="ch11.html" title="Chapter 11. Core Utilities">Chapter 11</a> describes the <code class="literal">DateFormat</code> class. As we said earlier, the
classes of the <code class="literal">java.text</code> package
overlap to a large degree with the capabilities of the <code class="literal">Scanner</code> and <code class="literal">printf</code>-style <code class="literal">Formatter</code>. Despite these new features, a number
of areas in the parsing of currencies, dates, and times can only be
handled with the <code class="literal">java.text</code>
package.</p><p>The <code class="literal">NumberFormat</code> class can be
used to format and parse currency, percentages, or plain old numbers.
<code class="literal">NumberFormat</code> is an abstract class, but
it has several useful factory methods that produce formatters for
different types of numbers. For example, to format or parse currency
strings, use <a id="I_indexterm10_id731256" class="indexterm"/><code class="literal">getCurrencyInstance()</code>
:</p><a id="I_10_tt617"/><pre class="programlisting"> <code class="kt">double</code> <code class="n">salary</code> <code class="o">=</code> <code class="mf">1234.56</code><code class="o">;</code>
<code class="n">String</code> <code class="n">here</code> <code class="o">=</code> <code class="c1">// $1,234.56</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getCurrencyInstance</code><code class="o">().</code><code class="na">format</code><code class="o">(</code><code class="n">salary</code><code class="o">);</code>
<code class="n">String</code> <code class="n">italy</code> <code class="o">=</code> <code class="c1">// L 1.234,56</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getCurrencyInstance</code><code class="o">(</code><code class="n">Locale</code><code class="o">.</code><code class="na">ITALY</code><code class="o">).</code><code class="na">format</code><code class="o">(</code><code class="n">salary</code><code class="o">);</code></pre><p>The first statement generates an American salary, with a dollar
sign, a comma to separate thousands, and a period as a decimal point. The
second statement presents the same string in Italian, with a lire sign, a
period to separate thousands, and a comma as a decimal point. Remember
that <code class="literal">NumberFormat</code> worries about format
only; it doesn’t attempt to do currency conversion. We can go the other
way and parse a formatted value using the <code class="literal">parse()</code> method, as we’ll see in the next
example.</p><p>Likewise, <a id="I_indexterm10_id731298" class="indexterm"/><code class="literal">getPercentInstance()</code>
returns a formatter you can use for generating and parsing percentages. If
you do not specify a <code class="literal">Locale</code> when
calling a <code class="literal">getInstance()</code> method, the
default <code class="literal">Locale</code> is used:</p><a id="I_10_tt618"/><pre class="programlisting"> <code class="kt">double</code> <code class="n">progress</code> <code class="o">=</code> <code class="mf">0.44</code><code class="o">;</code>
<code class="n">NumberFormat</code> <code class="n">pf</code> <code class="o">=</code> <code class="n">NumberFormat</code><code class="o">.</code><code class="na">getPercentInstance</code><code class="o">();</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">pf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="n">progress</code><code class="o">)</code> <code class="o">);</code> <code class="c1">// "44%"</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">pf</code><code class="o">.</code><code class="na">parse</code><code class="o">(</code><code class="s">"77.2%"</code><code class="o">)</code> <code class="o">);</code> <code class="c1">// "0.772"</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code><code class="n">ParseException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code></pre><p>And if you just want to generate and parse plain old numbers, use a
<code class="literal">NumberFormat</code> returned by <code class="literal">getInstance()</code> or its equivalent, <a id="I_indexterm10_id731350" class="indexterm"/><code class="literal">getNumberInstance()</code>
:</p><a id="I_10_tt619"/><pre class="programlisting"> <code class="n">NumberFormat</code> <code class="n">guiseppe</code> <code class="o">=</code> <code class="n">NumberFormat</code><code class="o">.</code><code class="na">getInstance</code><code class="o">(</code><code class="n">Locale</code><code class="o">.</code><code class="na">ITALY</code><code class="o">);</code>
<code class="c1">// defaults to Locale.US</code>
<code class="n">NumberFormat</code> <code class="n">joe</code> <code class="o">=</code> <code class="n">NumberFormat</code><code class="o">.</code><code class="na">getInstance</code><code class="o">();</code>
<code class="k">try</code> <code class="o">{</code>
<code class="kt">double</code> <code class="n">theValue</code> <code class="o">=</code> <code class="n">guiseppe</code><code class="o">.</code><code class="na">parse</code><code class="o">(</code><code class="s">"34.663,252"</code><code class="o">).</code><code class="na">doubleValue</code><code class="o">();</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">joe</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="n">theValue</code><code class="o">));</code> <code class="c1">// "34,663.252"</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code><code class="n">ParseException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code></pre><p>We use <code class="literal">guiseppe</code> to parse a number
in Italian format (periods separate thousands, comma is the decimal
point). The return type of <code class="literal">parse()</code> is
<code class="literal">Number</code>, so we use the <a id="I_indexterm10_id731391" class="indexterm"/><code class="literal">doubleValue()</code> method to
retrieve the value of the <code class="literal">Number</code> as a
<code class="literal">double</code>. Then we use <code class="literal">joe</code> to format the number correctly for the
default (U.S.) locale.</p><p>Here’s a list of the factory methods for text formatters in the
<code class="literal">java.text</code> package. Again, we’ll look at
the <code class="literal">DateFormat</code> methods in the next
chapter.</p><a id="I_10_tt620"/><pre class="programlisting"> <code class="n">NumberFormat</code><code class="o">.</code><code class="na">getCurrencyInstance</code><code class="o">()</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getCurrencyInstance</code><code class="o">(</code><code class="n">Locale</code> <code class="n">inLocale</code><code class="o">)</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getInstance</code><code class="o">()</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getInstance</code><code class="o">(</code><code class="n">Locale</code> <code class="n">inLocale</code><code class="o">)</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getNumberInstance</code><code class="o">()</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getNumberInstance</code><code class="o">(</code><code class="n">Locale</code> <code class="n">inLocale</code><code class="o">)</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getPercentInstance</code><code class="o">()</code>
<code class="n">NumberFormat</code><code class="o">.</code><code class="na">getPercentInstance</code><code class="o">(</code><code class="n">Locale</code> <code class="n">inLocale</code><code class="o">)</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getDateInstance</code><code class="o">()</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getDateInstance</code><code class="o">(</code><code class="kt">int</code> <code class="n">style</code><code class="o">)</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getDateInstance</code><code class="o">(</code><code class="kt">int</code> <code class="n">style</code><code class="o">,</code> <code class="n">Locale</code> <code class="n">aLocale</code><code class="o">)</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getDateTimeInstance</code><code class="o">()</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getDateTimeInstance</code><code class="o">(</code><code class="kt">int</code> <code class="n">dateStyle</code><code class="o">,</code> <code class="kt">int</code> <code class="n">timeStyle</code><code class="o">)</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getDateTimeInstance</code><code class="o">(</code><code class="kt">int</code> <code class="n">dateStyle</code><code class="o">,</code> <code class="kt">int</code> <code class="n">timeStyle</code><code class="o">,</code> <code class="n">Locale</code> <code class="n">aLocale</code><code class="o">)</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getInstance</code><code class="o">()</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getTimeInstance</code><code class="o">()</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getTimeInstance</code><code class="o">(</code><code class="kt">int</code> <code class="n">style</code><code class="o">)</code>
<code class="n">DateFormat</code><code class="o">.</code><code class="na">getTimeInstance</code><code class="o">(</code><code class="kt">int</code> <code class="n">style</code><code class="o">,</code> <code class="n">Locale</code> <code class="n">aLocale</code><code class="o">)</code></pre><p>Thus far, we’ve seen how to format numbers as text. Now, we’ll take
a look at a class, <a id="I_indexterm10_id731453" class="indexterm"/><code class="literal">ChoiceFormat</code>, that maps
numerical ranges to text. <code class="literal">ChoiceFormat</code>
is constructed by specifying the numerical ranges and the strings that
correspond to them. One constructor accepts an array of <code class="literal">double</code>s and an array of <code class="literal">String</code>s, where each string corresponds to the
range running from the matching number up to (but not including) the next
number in the array:</p><a id="I_10_tt621"/><pre class="programlisting"> <code class="kt">double</code><code class="o">[]</code> <code class="n">limits</code> <code class="o">=</code> <code class="k">new</code> <code class="kt">double</code> <code class="o">[]</code> <code class="o">{</code><code class="mi">0</code><code class="o">,</code> <code class="mi">20</code><code class="o">,</code> <code class="mi">40</code><code class="o">};</code>
<code class="n">String</code><code class="o">[]</code> <code class="n">labels</code> <code class="o">=</code> <code class="k">new</code> <code class="n">String</code> <code class="o">[]</code> <code class="o">{</code><code class="s">"young"</code><code class="o">,</code> <code class="s">"less young"</code><code class="o">,</code> <code class="s">"old"</code><code class="o">};</code>
<code class="n">ChoiceFormat</code> <code class="n">cf</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ChoiceFormat</code><code class="o">(</code><code class="n">limits</code><code class="o">,</code> <code class="n">labels</code><code class="o">);</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">cf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="mi">12</code><code class="o">));</code> <code class="c1">//"young"</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">cf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="mi">26</code><code class="o">));</code> <code class="c1">// "less young"</code></pre><p>You can specify both the limits and the labels using a special
string in an alternative <code class="literal">ChoiceFormat</code>
constructor:</p><a id="I_10_tt622"/><pre class="programlisting"> <code class="n">ChoiceFormat</code> <code class="n">cf</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ChoiceFormat</code><code class="o">(</code><code class="s">"0#young|20#less young|40#old"</code><code class="o">);</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">cf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="mi">40</code><code class="o">));</code> <code class="c1">// old</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">cf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="mi">50</code><code class="o">));</code> <code class="c1">// old</code></pre><p>The limit and value pairs are separated by vertical bars (<code class="literal">|</code>); the number sign (<code class="literal">#</code>) separates each limit from its corresponding
value.</p><p><code class="literal">ChoiceFormat</code> is most useful for
handling pluralization in messages, enabling you to avoid hideous
constructions such as, “you have one file(s) open.” You can create
readable error messages by using <code class="literal">ChoiceFormat</code> along with the <code class="literal">MessageFormat</code> class.</p><div class="sect2" title="MessageFormat"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-10-SECT-6.1"/>MessageFormat</h2></div></div></div><p><a id="idx10532" class="indexterm"/> <code class="literal">MessageFormat</code> is a
string formatter that uses a pattern string in the same way that
<code class="literal">printf()</code> formatting does. <code class="literal">MessageFormat</code> has largely been replaced by
<code class="literal">printf()</code>, which has more options and
is more widely used outside of Java. Nonetheless, some may still prefer
<code class="literal">MessageFormat</code>’s style, which is a bit
less cryptic than that of <code class="literal">printf()</code>.
<code class="literal">MessageFormat</code> has a static formatting
method, <code class="literal">MessageFormat.format()</code>,
paralleling the print-style formatting of <code class="literal">String.format()</code>.</p><p>Arguments in a <code class="literal">MessageFormat</code>
format string are delineated by curly brackets and may include
information about how they should be formatted. Each argument consists
of a number, an optional type, and an optional style, as summarized in
<a class="xref" href="ch10s06.html#learnjava3-CHP-10-TABLE-8" title="Table 10-8. MessageFormat arguments">Table 10-8</a>.</p><div class="table"><a id="learnjava3-CHP-10-TABLE-8"/><p class="title">Table 10-8. MessageFormat arguments</p><div class="table-contents"><table summary="MessageFormat arguments" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; "><colgroup><col/><col/></colgroup><thead><tr><th style="text-align: left"><p>Type</p></th><th style="text-align: left"><p>Styles</p></th></tr></thead><tbody><tr><td style="text-align: left"><p> <a id="I_indexterm10_id731673" class="indexterm"/> <code class="literal">Choice</code>
</p></td><td style="text-align: left"><p> <em class="replaceable"><code>pattern</code></em>
</p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm10_id731699" class="indexterm"/> <code class="literal">Date</code>
</p></td><td style="text-align: left"><p> <code class="literal">short</code>, <code class="literal">medium</code>, <code class="literal">long</code>, <code class="literal">full</code>,
<em class="replaceable"><code>pattern</code></em></p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm10_id731745" class="indexterm"/> <code class="literal">Number</code>
</p></td><td style="text-align: left"><p> <code class="literal">integer</code>, <code class="literal">percent</code>, <code class="literal">currency</code>,
<em class="replaceable"><code>pattern</code></em></p></td></tr><tr><td style="text-align: left"><p> <a id="I_indexterm10_id731786" class="indexterm"/> <code class="literal">Time</code>
</p></td><td style="text-align: left"><p> <code class="literal">short</code>, <code class="literal">medium</code>, <code class="literal">long</code>, <code class="literal">full</code>,
<em class="replaceable"><code>pattern</code></em></p></td></tr></tbody></table></div></div><p>Let’s use an example to clarify this:</p><a id="I_10_tt623"/><pre class="programlisting"> <code class="c1">//Equivalent to String.format("You have %s messages.", "no");</code>
<code class="n">MessageFormat</code><code class="o">.</code><code class="na">format</code><code class="o">(</code><code class="s">"You have {0} messages."</code><code class="o">,</code> <code class="s">"no"</code><code class="o">);</code></pre><p>The special incantation <code class="literal">{0}</code>
means “use element zero of the arguments supplied to the <code class="literal">format()</code> method.” When we generate a message
by calling <code class="literal">format()</code>, we pass in
values to replace the placeholders (<code class="literal">{0}</code>, <code class="literal">{1}</code>,
... ) in the template. In this case, we pass the string “no” as <code class="literal">arguments[0]</code>, yielding the result, <code class="literal">You have no messages.</code></p><p>Let’s try this example again, but this time, we’ll format a number
and a date instead of a string argument:</p><a id="I_10_tt624"/><pre class="programlisting"> <code class="n">MessageFormat</code> <code class="n">mf</code> <code class="o">=</code> <code class="k">new</code> <code class="n">MessageFormat</code><code class="o">(</code>
<code class="s">"You have {0, number, integer} messages on {1, date, long}."</code><code class="o">);</code>
<code class="c1">// "You have 93 messages on April 10, 2002."</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">mf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code> <code class="mi">93</code><code class="o">,</code> <code class="k">new</code> <code class="n">Date</code><code class="o">()</code> <code class="o">)</code> <code class="o">);</code></pre><p>In this example, we need to fill in two spaces in the template, so
we need two arguments. The first must be a number and is formatted as an
integer. The second must be a <code class="literal">Date</code>
and is printed in the <code class="literal">long</code>
format.</p><p>This is still sloppy. What if there is only one message? To make
this grammatically correct, we can embed a <code class="literal">ChoiceFormat</code>-style pattern string in our
<code class="literal">MessageFormat</code> pattern string:</p><a id="I_10_tt625"/><pre class="programlisting"> <code class="n">MessageFormat</code> <code class="n">mf</code> <code class="o">=</code> <code class="k">new</code> <code class="n">MessageFormat</code><code class="o">(</code>
<code class="s">"You have {0, number, integer} message{0, choice, 0#s|1#|2#s}."</code><code class="o">);</code>
<code class="c1">// "You have 1 message."</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">mf</code><code class="o">.</code><code class="na">format</code><code class="o">(</code> <code class="mi">1</code> <code class="o">)</code> <code class="o">);</code></pre><p>In this case, we use the first argument twice: once to supply the
number of messages and once to provide input to the <code class="literal">ChoiceFormat</code> pattern. The pattern says to add
an <code class="literal">s</code> if the argument has the value
<code class="literal">0</code> or is <code class="literal">2</code> or more.</p><p>When writing internationalized programs, you can use resource
bundles to supply not only the text of messages, but also the format
strings for your <code class="literal">MessageFormat</code>
objects. In this way, you can automatically format messages that are in
the appropriate language with dates and other language-dependent fields
handled appropriately and in the appropriate order. Because arguments in
the format string are numbered, you can refer to them in any location.
For example, in English, you might say, “Disk C has 123 files”; in some
other language, you might say, “123 files are on Disk C.” You could
implement both messages with the same set of arguments:</p><a id="I_10_tt626"/><pre class="programlisting"> <code class="n">MessageFormat</code> <code class="n">m1</code> <code class="o">=</code> <code class="k">new</code> <code class="n">MessageFormat</code><code class="o">(</code>
<code class="s">"Disk {0} has {1, number, integer} files."</code><code class="o">);</code>
<code class="n">MessageFormat</code> <code class="n">m2</code> <code class="o">=</code> <code class="k">new</code> <code class="n">MessageFormat</code><code class="o">(</code>
<code class="s">"{1, number, integer} files are on disk {0}."</code><code class="o">);</code></pre><p>In real life, the code could be more compact; you’d use only a
single <code class="literal">MessageFormat</code> object,
initialized with a string taken from a resource bundle. Or you’d likely
want to use the static <code class="literal">format</code> method
or switch to <code class="literal">printf()</code>
entirely.<a id="I_indexterm10_id732009" class="indexterm"/><a id="I_indexterm10_id732016" class="indexterm"/><a id="I_indexterm10_id732023" class="indexterm"/></p></div></div></body></html>