|
java.text 包允許通過與特定語言無關(guān)的方式格式化文本消息、日期和數(shù)值。 1. 數(shù)據(jù)格式化相關(guān)類介紹 類 功能介紹 java.util.* Locale 表示一個(gè)語言和區(qū)域的特定組合 ResourceBundle ListResourceBundle PropertyResourceBundle 獲取本地化資源中(可以表現(xiàn)為類和資源文件)的信息 Calendar GregorianCalendar 日歷的支持 TimeZone SimpleTimeZone 時(shí)區(qū)的支持 Currency 單獨(dú)處理和貨幣相關(guān)的操作 java.text.* Format NumberFormat DecimalFormat 格式化 格式化數(shù)字、貨幣以及百分?jǐn)?shù) ChoiceFormat 處理復(fù)數(shù)形式 DateFormat SimpleDateFormat 日期和時(shí)間的格式化 MessageFormat 消息的格式化 DecimalFormatSymbols、DateFormatSymbols 自定義格式化中的符號集 FieldPosition 被Format及其子類用來在格式化輸出中標(biāo)識字段 Collator RuleBasedCollator 字符串操作 比較字符串 CollationElementIterator 獲得一個(gè)字符串中單個(gè)字符的枚舉信息 CollationKey 優(yōu)化比較性能 BreakIterator 獲得文本中的個(gè)體信息,比如字符、單詞、句子以及整行等信息 java.lang.* Character 檢查字符屬性 2. 國際化及MessageFormat類 MessageFormat 運(yùn)行開發(fā)者輸出文本中的變量的格式,它主要用于國際化。它是一個(gè)強(qiáng)大的類,就像下面的例子展示的那樣: String message = "Once upon a time ({1,date}, around about {1,time,short}), there " + "was a humble developer named Geppetto who slaved for " + "{0,number,integer} days with {2,number,percent} complete user " + "requirements. "; Object[ ] variables = new Object[ ] { new Integer(4), new Date( ), new Double(0.21) } String output = MessageFormat.format( message, variables ); System.out.println(output); 隱藏在信息中的是描述輸出的格式的一種短小的代碼,范例的輸出如下: Once upon a time (Nov 3, 2002, around about 1:35 AM), there was a humble developer named Geppetto who slaved for 4 days with 21% complete user requirements. 如果相同的信息需要被重復(fù)輸出但是變量的值不同,那么創(chuàng)建一個(gè)MessageFormat 對象并給出信息。下面是上面的例子的修正版: // String output = MessageFormat.format( message, variables ); // 變?yōu)? MessageFormat formatter = new MessageFormat(message); String output = formatter.format(variables); 除了可以處理日期、時(shí)間、數(shù)字和百分?jǐn)?shù)外,MessageFormat 也可以處理貨幣,運(yùn)行更多的數(shù)字格式的控制并且允許指定ChoiceFormat。 MessageFormat 是一個(gè)極好的類,它應(yīng)該經(jīng)常被使用但是現(xiàn)在還沒有。它的最大的缺點(diǎn)是數(shù)據(jù)是被作為變量傳遞而不是一個(gè)Properties對象。一個(gè)簡單的解決辦法是寫一個(gè)封裝類,它會預(yù)解析字符串為格式化的結(jié)果,將Properties的key轉(zhuǎn)換為一個(gè)數(shù)組索引,順序是Properties.keys( )返回的順序。 3. 數(shù)值格式化 3.1. 有關(guān)numberformat 如果您來自美國,您會在較大的數(shù)值中間放置逗號來表示千和百萬(等等,每三個(gè)數(shù)值使用一個(gè)逗號)。對于浮點(diǎn)數(shù),您將在整數(shù)部分和小數(shù)部分之間放置小數(shù)點(diǎn)。對于金錢,貨幣符號 $ 放在金額的前面。如果 您從來沒有到過美國以外的地方,可能就不會關(guān)心用英鎊(£)來格式化的英國貨幣,或者用歐元(?)來表示的其他歐洲國家的貨幣。 對于那些我們確實(shí)關(guān)心的貨幣,我們可以使用 NumberFormat 及其相關(guān)的類來格式化它們。開發(fā)人員使用 NumberFormat 類來讀取用戶輸入的數(shù)值,并格式化將要顯示給用戶看的輸出。 在Java的I/O里,并沒有所謂的型別,不管是int、long、double…最後都是以String輸出,所以如果要讓數(shù)字以特定格式輸出,需透過Java提供的兩個(gè)類別java.text.NumberFormat和java.text.DecimalFormat將數(shù)字格式化後再輸出。 在開始使用NumberFormat時(shí),應(yīng)先用getInstance取得NumberFormat的實(shí)體,范例12中的setMaximumIntegerDigits和setMinimumFractionDigits是用來設(shè)定整數(shù)和小數(shù)的位數(shù),另外還有setMinimumIntegerDigits和setMaximumFractionDigits也是同樣功能。這些設(shè)定如有沖突,Java以最後設(shè)定的為準(zhǔn)。 import java.text.*; public class myFormat { public myFormat() { NumberFormat nf = NumberFormat.getInstance(); double dblNum = Math.PI; System.out.println(dblNum); nf.setMaximumIntegerDigits(5); nf.setMinimumFractionDigits(4); System.out.println("PI: " + nf.format(dblNum)); } public static void main(String[] args) { myFormat myFormat1 = new myFormat(); } } 與 DateFormat 類似,NumberFormat 是一個(gè)抽象類。您永遠(yuǎn)不會創(chuàng)建它的實(shí)例??相反, 您總是使用它的子類。雖然可以通過子類的構(gòu)造函數(shù)直接創(chuàng)建子類,不過NumberFormat 類提供了一系列 getXXXInstance() 方法,用以獲得不同類型的數(shù)值類的特定地區(qū)版本。這樣的方法共有五個(gè): • getCurrencyInstance() • getInstance() • getIntegerInstance() • getNumberInstance() • getPercentInstance() 具體使用哪一個(gè)方法取決于您想要顯示的數(shù)值類型(或者想要接受的輸入類型)。每個(gè)方法都提供了兩個(gè)版本??一個(gè)版本適用于當(dāng)前地區(qū),另一個(gè)版本接受一個(gè) Locale作為參數(shù),以便可能地指定一個(gè)不同的地區(qū)。 使用 NumberFormat 的基本過程是獲得一個(gè)實(shí)例并使用該實(shí)例。挑選恰當(dāng)?shù)膶?shí)例的確需要費(fèi)一番思量。通常 您不希望使用通用的 getInstance 或者 getNumberInstance() 版本,因?yàn)?nbsp;您不確切知道您將會得到什么。相反,您會使用像 getIntegerInstance() 這樣的方法,因?yàn)?nbsp;您希望把某些內(nèi)容顯示為整數(shù)而不需要任何小數(shù)值。清單1展示了這一點(diǎn),我們在其中把數(shù)值 54321 顯示為適合于美國和德國的格式。 清單 1. 使用 NumberFormat import java.text.*; import java.util.*; public class IntegerSample { public static void main(String args[]) { int amount = 54321; NumberFormat usFormat = NumberFormat.getIntegerInstance(Locale.US); System.out.println(usFormat.format(amount)); NumberFormat germanFormat = NumberFormat.getIntegerInstance(Locale.GERMANY); System.out.println(germanFormat.format(amount)); } } 運(yùn)行該代碼將產(chǎn)生如清單2所示的輸出。注意第一種格式(美國)中的逗號分隔符和第二種格式中的點(diǎn)號分隔符。 清單 2. NumberFormat 輸出 54,321 54.321 雖然 NumberFormat 是一個(gè)抽象類,并且您將通過像 getIntegerInstance() 這樣的各種方法來使用它的實(shí)例,但是 DecimalFormat 類提供了該類的一個(gè)具體版本。 您可以顯式地指定字符模式,用以確定如何顯示正數(shù)、負(fù)數(shù)、小數(shù)和指數(shù)。如果不喜歡用于不同地區(qū)的預(yù)定義格式,您可以創(chuàng)建自己的格式。(在內(nèi)部,或許 NumberFormat 使用的就是 DecimalFormat。)。 3.2. 使用 Currency 進(jìn)行貨幣計(jì)算 前面提到過的 getCurrency() 和setCurrency() 方法返回新的 java.util.Currency 類的一個(gè)實(shí)例。這個(gè)類允許訪問不同國家的 ISO 4217 貨幣代碼。雖然自從 getCurrencyInstance() 引入以來您就能配合 NumberFormat 一起使用它,然而除了它們的數(shù)字顯示外, 您永遠(yuǎn)不能獲得或顯示某個(gè)地區(qū)的貨幣符號。有了Currency 類,現(xiàn)在很容易就可以做到這一點(diǎn)。 正如前面提到過的,貨幣代碼來自ISO 4217。通過傳入某個(gè)國家的 Locale 或者貨幣的實(shí)際字母代碼,Currency.getInstance() 將返回一個(gè)有效的 Currency 對象。NumberFormat 的 getCurrency() 方法將在創(chuàng)建特定地區(qū)的貨幣實(shí)例之后做同樣的事情。 清單7顯示了如何獲得貨幣實(shí)例,以及如何格式化將要顯示為貨幣的數(shù)值。記住這些轉(zhuǎn)換僅用于顯示。如果需要在貨幣之間轉(zhuǎn)換金額,應(yīng)該在確定如何顯示值之前進(jìn)行轉(zhuǎn)換。 清單 7. 使用 getCurrencyInstance() 和 Currency import java.text.*; import java.util.*; import java.awt.*; import javax.swing.*; public class CurrencySample { public static void main(String args[]) { StringBuffer buffer = new StringBuffer(100); Currency dollars = Currency.getInstance("USD"); Currency pounds = Currency.getInstance(Locale.UK); buffer.append("Dollars: "); buffer.append(dollars.getSymbol()); buffer.append("\n"); buffer.append("Pound Sterling: "); buffer.append(pounds.getSymbol()); buffer.append("\n-----\n"); double amount = 5000.25; NumberFormat usFormat = NumberFormat.getCurrencyInstance(Locale.US); buffer.append("Symbol: "); buffer.append(usFormat.getCurrency().getSymbol()); buffer.append("\n"); buffer.append(usFormat.format(amount)); buffer.append("\n"); NumberFormat germanFormat = NumberFormat.getCurrencyInstance(Locale.GERMANY); buffer.append("Symbol: "); buffer.append(germanFormat.getCurrency().getSymbol()); buffer.append("\n"); buffer.append(germanFormat.format(amount)); JFrame frame = new JFrame("Currency"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTextArea ta = new JTextArea(buffer.toString()); JScrollPane pane = new JScrollPane(ta); frame.getContentPane().add(pane, BorderLayout.CENTER); frame.setSize(200, 200); frame.show(); } } 遺憾的是,為歐元或者英鎊返回的貨幣符號不是實(shí)際的符號,而是三位的貨幣代碼(來自 ISO 4217)。然而在使用 getCurrencyInstance() 的情況下,實(shí)際的符號將會顯示出來, 3.3. DecimalFormat NumberFormat.getInstance()方法返回NumberFormat的一個(gè)實(shí)例(實(shí)際上是NumberFormat具體的一個(gè)子類,例如DecimalFormat), 這適合根據(jù)本地設(shè)置格式化一個(gè)數(shù)字。你也可以使用非缺省的地區(qū)設(shè)置,例如德國。然后格式化方法根據(jù)特定的地區(qū)規(guī)則格式化數(shù)字。這個(gè)程序也可以使用一個(gè)簡單的形式: NumberFormat.getInstance().format(1234.56) 但是保存一個(gè)格式然后重用更加有效。國際化是格式化數(shù)字時(shí)的一個(gè)大問題。 另一個(gè)是對格式的有效控制,例如指定小數(shù)部分的位數(shù),下面是解決這個(gè)問題的一個(gè)簡單例子: import java.text.DecimalFormat; import java.util.Locale; public class DecimalFormat2 { public static void main(String args[]) { // 得到本地的缺省格式 DecimalFormat df1 = new DecimalFormat("####.000"); System.out.println(df1.format(1234.56)); // 得到德國的格式 Locale.setDefault(Locale.GERMAN); DecimalFormat df2 = new DecimalFormat("####.000"); System.out.println(df2.format(1234.56)); } } 在這個(gè)例子中設(shè)置了數(shù)字的格式,使用像"####.000"的符號。這個(gè)模式意味著在小數(shù)點(diǎn)前有四個(gè)數(shù)字,如果不夠就空著,小數(shù)點(diǎn)后有三位數(shù)字,不足用0補(bǔ)齊。程序的輸出: 1234.560 1234,560 相似的,也可以控制指數(shù)形式的格式,例如: import java.text.DecimalFormat; public class DecimalFormat3 { public static void main(String args[]) { DecimalFormat df = new DecimalFormat("0.000E0000"); System.out.println(df.format(1234.56)); } } 輸出: 1.235E0003 對于百分?jǐn)?shù): import java.text.NumberFormat; public class DecimalFormat4 { public static void main(String args[]) { NumberFormat nf = NumberFormat.getPercentInstance(); System.out.println(nf.format(0.47)); } } 輸出: 47% 至此,你已經(jīng)看到了格式化數(shù)字的幾個(gè)不同的技術(shù)。另一方面,如何讀取并解析包含格式化的數(shù)字的字符串?解析支持包含在NumberFormat中。例如: import java.util.Locale; import java.text.NumberFormat; import java.text.ParseException; public class DecimalFormat5 { public static void main(String args[]) { // 本地格式 NumberFormat nf1 = NumberFormat.getInstance(); Object obj1 = null; // 基于格式的解析 try { obj1 = nf1.parse("1234,56"); } catch (ParseException e1) { System.err.println(e1); } System.out.println(obj1); // 德國格式 NumberFormat nf2 =NumberFormat.getInstance(Locale.GERMAN); Object obj2 = null; // 基于格式的解析 try { obj2 = nf2.parse("1234,56"); } catch (ParseException e2) { System.err.println(e2); } System.out.println(obj2); } } 這個(gè)例子分兩部分,都是解析一個(gè)字符串:"1234,56"。第一部分使用本地格式解析,第二部分使用德國格式解析。當(dāng)程序在美國運(yùn)行,結(jié)果是: 123456 1234.56 換句話說,"1234,56"在美國被認(rèn)為是一個(gè)巨大的整數(shù)"123456"而在德國被認(rèn)為是一個(gè)小數(shù)"1234.56"。 3.4. DecimalFormat 和 NumberFormat的聯(lián)系 在上面的例子中, DecimalFormat 和 NumberFormat 都被使用了。DecimalFormat 常用于獲得很好的格式控制,而NumberFormat 常用于指定不同于本地的地區(qū)。如何結(jié)合兩個(gè)類呢? 答案圍繞著這樣的事實(shí):DecimalFormat是NumberFormat的一個(gè)子類,其實(shí)例被指定為特定的地區(qū)。因此,你可以使用NumberFormat.getInstance 指定一個(gè)地區(qū),然后將結(jié)構(gòu)強(qiáng)制轉(zhuǎn)換為一個(gè)DecimalFormat對象。文檔中提到這個(gè)技術(shù)可以在大多情況下適用,但是你需要用try/catch 塊包圍強(qiáng)制轉(zhuǎn)換以防轉(zhuǎn)換不能正常工作 (大概在非常不明顯得情況下使用一個(gè)奇異的地區(qū))。下面是一個(gè)這樣的例子: import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; public class DecimalFormat6 { public static void main(String args[]) { DecimalFormat df = null; // 得到一個(gè)NumberFormat 對象并 // 強(qiáng)制轉(zhuǎn)換為一個(gè) DecimalFormat 對象 try { df = (DecimalFormat)NumberFormat.getInstance(Locale.GERMAN); } catch (ClassCastException e) { System.err.println(e); } // 設(shè)置格式模式 df.applyPattern("####.00000"); // format a number System.out.println(df.format(1234.56)); } } getInstance() 方法獲得格式,然后調(diào)用applyPattern()方法設(shè)置格式模式,輸出: 1234,56000 如果你不關(guān)心國際化,可以直接使用DecimalFormat 。 其中v 為未處理的double,scale為需求精度,返回需要小數(shù)位數(shù)的double public static double round(double v,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } package com.minght.sys.util; import java.text.*; import java.util.*; import java.math.*; /** * <p>Title: 格式化:開源,開放</p> * <p>Description: opeansource</p> * <p>Copyright: Copyright (c) 2004</p> * <p>Company: ?海棠</p> * @author HaiTang Ming * @version 1.0 */ public class ObjectFormat { public ObjectFormat() { } /** * 將給定的數(shù)字按給定的形式輸出 * @param d double * @param pattern String * #:表示有數(shù)字則輸出數(shù)字,沒有則空,如果輸出位數(shù)多于#的位數(shù),則超長輸入 * 0:有數(shù)字則輸出數(shù)字,沒有補(bǔ)0 * 對于小數(shù),有幾個(gè)?;?,就保留幾位的小數(shù); * 例如: "###.00" -->表示輸出的數(shù)值保留兩位小數(shù),不足兩位的補(bǔ)0,多于兩位的四舍五入 * "###.0#" -->表示輸出的數(shù)值可以保留一位或兩位小數(shù);整數(shù)顯示為有一位小數(shù),一位或兩位小數(shù)的按原樣顯示,多于兩位的四舍五入; * "###" --->表示為整數(shù),小數(shù)部分四舍五入 * ".###" -->12.234顯示為.234 * "#,###.0#" -->表示整數(shù)每隔3位加一個(gè)","; * @param l Locale * @return String */ public static String formatNumber(double d,String pattern,Locale l){ String s = ""; try{ DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(l); nf.applyPattern(pattern); s = nf.format(d); }catch(Exception e){ e.printStackTrace(); Debug.println(" formatNumber is error!"); } return s; } /** * 按缺省的區(qū)域輸出數(shù)字形式 * @param d double * @param pattern String * @return String */ public static String formatNumber(double d,String pattern){ return formatNumber(d,pattern,Locale.getDefault()); } /** * 格式化貨幣 * @param d double * @param pattern String * "\u00A4#,###.00" :顯示為 ¥1,234,234.10 * @param l Locale * @return String */ public static String formatCurrency(double d,String pattern,Locale l){ String s = ""; try{ DecimalFormat nf = (DecimalFormat) NumberFormat.getCurrencyInstance(l); nf.applyPattern(pattern); s = nf.format(d); }catch(Exception e){ e.printStackTrace(); Debug.println(" formatNumber is error!"); } return s; } /** * 使用默認(rèn)區(qū)域的指定方式顯示貨幣 * @param d double * @param pattern String * @return String */ public static String formatCurrency(double d,String pattern){ return formatCurrency(d,pattern,Locale.getDefault()); } /** * 使用默認(rèn)方式顯示貨幣: * 例如:¥12,345.46 默認(rèn)保留2位小數(shù),四舍五入 * @param d double * @return String */ public static String formatCurrency(double d){ String s = ""; try{ DecimalFormat nf = (DecimalFormat) NumberFormat.getCurrencyInstance(); s = nf.format(d); }catch(Exception e){ e.printStackTrace(); Debug.println(" formatNumber is error!"); } return s; } /** * 按指定區(qū)域格式化百分?jǐn)?shù) * @param d * @param pattern :"##,##.000%"-->不要忘記“%” * @param l * @return */ public static String formatPercent(double d,String pattern,Locale l){ String s = ""; try{ DecimalFormat df = (DecimalFormat)NumberFormat.getPercentInstance(l); df.applyPattern(pattern); s = df.format(d); }catch(Exception e){ Debug.print(e,"formatPercent is error!"); } return s; } /** * 使用默認(rèn)區(qū)域格式化百分?jǐn)?shù) * @param d * @param pattern * @return */ public static String formatPercent(double d,String pattern){ return formatPercent(d,pattern,Locale.getDefault()); } /** * 格式化百分?jǐn)?shù) * @param d * @return */ public static String formatPercent(double d){ String s = ""; try{ DecimalFormat df = (DecimalFormat)NumberFormat.getPercentInstance(); s = df.format(d); }catch(Exception e){ Debug.print(e,"formatPercent is error!"); } return s; } /** * 輸出數(shù)字的格式,如:1,234,567.89 * @param bd BigDecimal 要格式華的數(shù)字 * @param format String 格式 "###,##0" * @return String */ public static String numberFormat(BigDecimal bd, String format) { if (bd == null || "0".equals(bd.toString())) { return ""; } DecimalFormat bf = new DecimalFormat(format); return bf.format(bd); } public static void main(String[] args) { String s = formatCurrency(11123.89343,"$##,##.000"); System.out.println(s); } } |
|
|