Java中的格式化输出

说在前面:本文大部分内容和代码来自《Thinking in Java》。这本书真的是一本好书,强烈推荐。

在Java SE5(很久很久以前的版本)引入了format方法,这个方法跟C的printf方法很像。首先用个简单例子说明下如何使用format方法。

public static void main(String[] args) {
	int x = 5;
	double y = 5.129867;
	//旧的方式
	System.out.println("Row 1: [" + x + " " + y + "]");
	//新的方式
	System.out.format("Row 1: [%d %f]\n", x, y);
	//或
	System.out.printf("Row 1: [%d %f]\n", x, y);
}

输出结果

Row 1: [5 5.129867]
Row 1: [5 5.129867]
Row 1: [5 5.129867]

使用很简单,一个简单的格式化字符串,加上一串参数即可。formatprintf是等价的。我们可以看下printf方法的实现。

public PrintStream printf(String format, Object ... args) {
    return format(format, args);
}
再来看下 format方法的实现
private Formatter formatter;
……
public PrintStream format(String format, Object ... args) {
    try {
        synchronized (this) {
            ensureOpen();
            if ((formatter == null)
                || (formatter.locale() != Locale.getDefault()))
                formatter = new Formatter((Appendable) this);
            formatter.format(Locale.getDefault(), format, args);
        }
    } catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    } catch (IOException x) {
        trouble = true;
    }
    return this;
}

可以看到,format是通过Formatter类来实现内容格式化的。

在Java中,所有新的格式化功能都由java.util.Formatter类处理,可以将Formatter看作一个翻译器,它将你的格式化字符串与数据翻译成需要的结果。当你创建一个Formatter 对象的时候,需要向其构造器传递一些信息,告诉它最终的结果将向哪里输出。
再看一个例子,这次我们不直接使用 System.out.format,而是使用 java.util.Formatter来实现格式化输出内容的需求:
public class Turtle {
	private String name;
	private Formatter f;
	public Turtle(String name, Formatter f){
		this.name = name;
		this.f = f;
	}
	public void move(int x, int y){
		f.format("%s The Turtle is at (%d, %d)\n", name, x, y);
	}
	public static void main(String[] args) {
		Turtle tommy = new Turtle("Tommy", new Formatter(System.out));
		tommy.move(0, 0);
		tommy.move(3, 2);
		tommy.move(7, 2);
	}
}

输出结果:

Tommy The Turtle is at (0, 0)
Tommy The Turtle is at (3, 2)
Tommy The Turtle is at (7, 2)

Formatter的构造器可以接受多种输出目的地,比如上例中的PrintStream,或者OutputStreamFile等。有兴趣的可以查看Formatter的构造器。

看到这里你可能会想:在上面的例子中,只是简单的输出字符串句子,以前常用的字符串拼接也可以做到,而且并没有多麻烦呀?

那我们现在来看下Formatter的更强大的地方:控制空格与对齐

解释再多,不如来一个实例,我们看例子:

public class Receipt {
	private double total = 0;
	private Formatter f = new Formatter(System.out);
	public void printTitle(){
		f.format("%-15s %5s %10s\n", "Item", "Qty", "Price");
		f.format("%-15s %5s %10s\n", "----", "---", "-----");
	}
	public void print(String name, int qty, double price){
		f.format("%-15.15s %5d %10.2f\n", name, qty, price);
		total = total + price;
	}
	public void printTotal(){
		f.format("%-15s %5s %10.2f\n", "Tax", "", total*0.06);
		f.format("%-15s %5s %10s\n", "", "", "-----");
		f.format("%-15s %5s %10.2f\n", "Total", "", total*1.06);
	}
	public static void main(String[] args) {
		Receipt receipt = new Receipt();
		receipt.printTitle();
		receipt.print("Jack's Magic Beans", 4, 4.25);
		receipt.print("Princess Peas", 3, 5.1);
		receipt.print("Three Bears Proridge", 1, 14.29);
		receipt.printTotal();
	}
}

输出结果:

Item              Qty      Price
----              ---      -----
Jack's Magic Be     4       4.25
Princess Peas       3       5.10
Three Bears Pro     1      14.29
Tax                         1.42
                           -----
Total                      25.06

是不是很整齐?通过简洁的语法,Formatter提供了对空格与对齐的强大控制能力。

看完例子,我们来解释下上面的格式化字符串“%-15s %5s %10.2f\n”是啥意思。以下是其抽象的语法:

%[argument_index$][flags][width][.precision]conversion
最常见的就是通过width来控制一个域的大小。比如“%-15s”中的15。默认情况下,数据是右对齐,不过可以通过使用“-”来改变对齐方向。precision则有点特别,首先该值前面必须带小数点。比如“%10.2f”;其次应用于不同类型的数据转换时,precision的意义也不同。应用于String时,它表示打印String时输出字符的最大数量。而在将precison应用于浮点数时,则表示小数部分要显示出来的位数(默认是6位小数),如果小数位数过多则舍入,太少则在尾部补零。应用于整数,触发异常,因为整数没有小数部分。

最后补充下常用的类型转换字符:

类型转换字符表      
--------------------
d    整数型(十进制)      
c    Unicode字符     
b    Boolean值      
s    String        
f    浮点数(十进制)      
e    浮点数(科学计数)     
x    整数(十六进制)      
h    散列码(十六进制)     
%    字符“%”

转载于:https://my.oschina.net/cevin15/blog/664925

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值