數據格式化

java.text 包允許通過與特定語言無關的方式格式化文本消息、日期和數值。
1.    數據格式化相關類介紹
類    功能介紹
java.util.*    Locale    表示一個語言和區域的特定組合
    ResourceBundle    ListResourceBundle
PropertyResourceBundle    獲取本地化資源中(可以表現爲類和資源文件)的信息
    Calendar    GregorianCalendar    日曆的支持
    TimeZone    SimpleTimeZone    時區的支持
    Currency    單獨處理和貨幣相關的操作
java.text.*    Format    NumberFormat
     DecimalFormat    格式化    格式化數字、貨幣以及百分數
            ChoiceFormat        處理複數形式
        DateFormat    SimpleDateFormat        日期和時間的格式化
        MessageFormat             消息的格式化
    DecimalFormatSymbols、DateFormatSymbols        自定義格式化中的符號集
    FieldPosition        被Format及其子類用來在格式化輸出中標識字段
    Collator    RuleBasedCollator    字符串操作    比較字符串
    CollationElementIterator        獲得一個字符串中單個字符的枚舉信息
    CollationKey        優化比較性能
    BreakIterator        獲得文本中的個體信息,比如字符、單詞、句子以及整行等信息
java.lang.*    Character    檢查字符屬性

2.    國際化及MessageFormat類
MessageFormat 運行開發者輸出文本中的變量的格式,它主要用於國際化。它是一個強大的類,就像下面的例子展示的那樣: 
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. 
如果相同的信息需要被重複輸出但是變量的值不同,那麼創建一個MessageFormat 對象並給出信息。下面是上面的例子的修正版: 
// String output = MessageFormat.format( message, variables );
// 變爲:
MessageFormat formatter = new MessageFormat(message);
String output = formatter.format(variables); 
除了可以處理日期、時間、數字和百分數外,MessageFormat 也可以處理貨幣,運行更多的數字格式的控制並且允許指定ChoiceFormat。 
MessageFormat 是一個極好的類,它應該經常被使用但是現在還沒有。它的最大的缺點是數據是被作爲變量傳遞而不是一個Properties對象。一個簡單的解決辦法是寫一個封裝類,它會預解析字符串爲格式化的結果,將Properties的key轉換爲一個數組索引,順序是Properties.keys( )返回的順序。
3.    數值格式化
3.1.    有關numberformat
如果您來自美國,您會在較大的數值中間放置逗號來表示千和百萬(等等,每三個數值使用一個逗號)。對於浮點數,您將在整數部分和小數部分之間放置小數點。對於金錢,貨幣符號 $ 放在金額的前面。如果 您從來沒有到過美國以外的地方,可能就不會關心用英鎊(£)來格式化的英國貨幣,或者用歐元(?)來表示的其他歐洲國家的貨幣。
對於那些我們確實關心的貨幣,我們可以使用 NumberFormat 及其相關的類來格式化它們。開發人員使用 NumberFormat 類來讀取用戶輸入的數值,並格式化將要顯示給用戶看的輸出。
在Java的I/O裏,並沒有所謂的型別,不管是int、long、double…最後都是以String輸出,所以如果要讓數字以特定格式輸出,需透過Java提供的兩個類別java.text.NumberFormat和java.text.DecimalFormat將數字格式化後再輸出。
在開始使用NumberFormat時,應先用getInstance取得NumberFormat的實體,範例12中的setMaximumIntegerDigits和setMinimumFractionDigits是用來設定整數和小數的位數,另外還有setMinimumIntegerDigits和setMaximumFractionDigits也是同樣功能。這些設定如有衝突,Java以最後設定的爲準。
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 是一個抽象類。您永遠不會創建它的實例??相反, 您總是使用它的子類。雖然可以通過子類的構造函數直接創建子類,不過NumberFormat 類提供了一系列 getXXXInstance() 方法,用以獲得不同類型的數值類的特定地區版本。這樣的方法共有五個:
•    getCurrencyInstance() 
•    getInstance() 
•    getIntegerInstance() 
•    getNumberInstance() 
•    getPercentInstance()
具體使用哪一個方法取決於您想要顯示的數值類型(或者想要接受的輸入類型)。每個方法都提供了兩個版本??一個版本適用於當前地區,另一個版本接受一個 Locale作爲參數,以便可能地指定一個不同的地區。
使用 NumberFormat 的基本過程是獲得一個實例並使用該實例。挑選恰當的實例的確需要費一番思量。通常 您不希望使用通用的 getInstance 或者 getNumberInstance() 版本,因爲 您不確切知道您將會得到什麼。相反,您會使用像 getIntegerInstance() 這樣的方法,因爲 您希望把某些內容顯示爲整數而不需要任何小數值。清單1展示了這一點,我們在其中把數值 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));
  }
}
運行該代碼將產生如清單2所示的輸出。注意第一種格式(美國)中的逗號分隔符和第二種格式中的點號分隔符。
清單 2. NumberFormat 輸出
54,321
54.321
雖然 NumberFormat 是一個抽象類,並且您將通過像 getIntegerInstance() 這樣的各種方法來使用它的實例,但是 DecimalFormat 類提供了該類的一個具體版本。 您可以顯式地指定字符模式,用以確定如何顯示正數、負數、小數和指數。如果不喜歡用於不同地區的預定義格式,您可以創建自己的格式。(在內部,或許 NumberFormat 使用的就是 DecimalFormat。)。
3.2.    使用 Currency 進行貨幣計算
前面提到過的 getCurrency() 和setCurrency() 方法返回新的 java.util.Currency 類的一個實例。這個類允許訪問不同國家的 ISO 4217 貨幣代碼。雖然自從 getCurrencyInstance() 引入以來您就能配合 NumberFormat 一起使用它,然而除了它們的數字顯示外, 您永遠不能獲得或顯示某個地區的貨幣符號。有了Currency 類,現在很容易就可以做到這一點。
正如前面提到過的,貨幣代碼來自ISO 4217。通過傳入某個國家的 Locale 或者貨幣的實際字母代碼,Currency.getInstance() 將返回一個有效的 Currency 對象。NumberFormat 的 getCurrency() 方法將在創建特定地區的貨幣實例之後做同樣的事情。 清單7顯示瞭如何獲得貨幣實例,以及如何格式化將要顯示爲貨幣的數值。記住這些轉換僅用於顯示。如果需要在貨幣之間轉換金額,應該在確定如何顯示值之前進行轉換。
清單 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();
  }
}                
遺憾的是,爲歐元或者英鎊返回的貨幣符號不是實際的符號,而是三位的貨幣代碼(來自 ISO 4217)。然而在使用 getCurrencyInstance() 的情況下,實際的符號將會顯示出來,
3.3.    DecimalFormat
NumberFormat.getInstance()方法返回NumberFormat的一個實例(實際上是NumberFormat具體的一個子類,例如DecimalFormat), 這適合根據本地設置格式化一個數字。你也可以使用非缺省的地區設置,例如德國。然後格式化方法根據特定的地區規則格式化數字。這個程序也可以使用一個簡單的形式:
NumberFormat.getInstance().format(1234.56)
但是保存一個格式然後重用更加有效。國際化是格式化數字時的一個大問題。
另一個是對格式的有效控制,例如指定小數部分的位數,下面是解決這個問題的一個簡單例子:
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));
}
}
在這個例子中設置了數字的格式,使用像"####.000"的符號。這個模式意味着在小數點前有四個數字,如果不夠就空着,小數點後有三位數字,不足用0補齊。程序的輸出:
1234.560
1234,560
相似的,也可以控制指數形式的格式,例如:
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
對於百分數:
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%
至此,你已經看到了格式化數字的幾個不同的技術。另一方面,如何讀取並解析包含格式化的數字的字符串?解析支持包含在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);
}
}
這個例子分兩部分,都是解析一個字符串:"1234,56"。第一部分使用本地格式解析,第二部分使用德國格式解析。當程序在美國運行,結果是:
123456
1234.56
換句話說,"1234,56"在美國被認爲是一個巨大的整數"123456"而在德國被認爲是一個小數"1234.56"。
3.4.    DecimalFormat 和 NumberFormat的聯繫
在上面的例子中, DecimalFormat 和 NumberFormat 都被使用了。DecimalFormat 常用於獲得很好的格式控制,而NumberFormat 常用於指定不同於本地的地區。如何結合兩個類呢?
答案圍繞着這樣的事實:DecimalFormat是NumberFormat的一個子類,其實例被指定爲特定的地區。因此,你可以使用NumberFormat.getInstance 指定一個地區,然後將結構強制轉換爲一個DecimalFormat對象。文檔中提到這個技術可以在大多情況下適用,但是你需要用try/catch 塊包圍強制轉換以防轉換不能正常工作 (大概在非常不明顯得情況下使用一個奇異的地區)。下面是一個這樣的例子:
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class DecimalFormat6 {
public static void main(String args[]) {
DecimalFormat df = null;
// 得到一個NumberFormat 對象並
// 強制轉換爲一個 DecimalFormat 對象
try {
df = (DecimalFormat)NumberFormat.getInstance(Locale.GERMAN);
}
catch (ClassCastException e) {
System.err.println(e);
}
// 設置格式模式
df.applyPattern("####.00000");
// format a number
System.out.println(df.format(1234.56));
}
}
getInstance() 方法獲得格式,然後調用applyPattern()方法設置格式模式,輸出:
1234,56000
如果你不關心國際化,可以直接使用DecimalFormat 。
其中v 爲未處理的double,scale爲需求精度,返回需要小數位數的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() {
  }

  /**
   * 將給定的數字按給定的形式輸出
   * @param d double
   * @param pattern String
   *       #:表示有數字則輸出數字,沒有則空,如果輸出位數多於#的位數,則超長輸入
   *       0:有數字則輸出數字,沒有補0
   *          對於小數,有幾個#或0,就保留幾位的小數;
   *       例如:  "###.00" -->表示輸出的數值保留兩位小數,不足兩位的補0,多於兩位的四捨五入
   *              "###.0#" -->表示輸出的數值可以保留一位或兩位小數;整數顯示爲有一位小數,一位或兩位小數的按原樣顯示,多於兩位的四捨五入;
   *              "###" --->表示爲整數,小數部分四捨五入
   *              ".###" -->12.234顯示爲.234
   *              "#,###.0#"  -->表示整數每隔3位加一個",";
   * @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;

  }

  /**
   * 按缺省的區域輸出數字形式
   * @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;

  }
  /**
   * 使用默認區域的指定方式顯示貨幣
   * @param d double
   * @param pattern String
   * @return String
   */
  public static String formatCurrency(double d,String pattern){
    return formatCurrency(d,pattern,Locale.getDefault());
  }

  /**
   * 使用默認方式顯示貨幣:
   *     例如:¥12,345.46  默認保留2位小數,四捨五入
   * @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;

  }

  /**
   * 按指定區域格式化百分數
   * @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;
  }
  /**
   * 使用默認區域格式化百分數
   * @param d
   * @param pattern
   * @return
   */
 public static String formatPercent(double d,String pattern){
   return formatPercent(d,pattern,Locale.getDefault());
 }

 /**
  * 格式化百分數
  * @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;
 }

  /**
   * 輸出數字的格式,如:1,234,567.89
   * @param bd BigDecimal 要格式華的數字
   * @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);
  }

}

 
發佈了3 篇原創文章 · 獲贊 0 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章