Java民工的铁皮房

Consciousness Of Programming - wjywilliam 想飞,总是会飞的......
posts - 8, comments - 14, trackbacks - 0, articles - 9
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

眀海棠文集之数据格式化1.0

Posted on 2007-04-06 23:56 wjywilliam 阅读(404) 评论(0)  编辑  收藏 所属分类: Java

眀海棠文集之数据格式化1.0

 

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);
  }

}

转载原作者......


只有注册用户登录后才能发表评论。


网站导航: