0%
这是一片思考的空间 -- arthinking
Spring 重构&代码整洁之道 软件设计 JVM 并发编程 数据结构与算法 分布式 存储 网络 微服务 设计模式
Java技术栈 - 涉及Java技术体系

Java笔记 - Java中的格式化输出,Formatter类的介绍

本文主要内容

1、System.out.format()格式化方法的介绍();

2、Formatter类的介绍和使用:初始化需要传入用于输出的介质,如System.out;

3、格式化说明符:format字符串格式化参数语法和使用例子;

4、String.format()的介绍,内部也是基于Formatter的;

5、使用提示:如果只需要使用format()方法一次,String.format()方法使用起来会很方便。

我们知道C语言中有printf()这样的格式化函数,类似这样的:

printf("data: [%d %f]\n", x, y);

1、Java中也提供了类似的格式化方法:System.out.format();

Java SE5引入的format方法可以用于PrintStream或PrintWriter对象(这里不介绍了),其中也包括System.out,下面就是一个使用例子:

int x = 1;
double y = 3.1415926;
System.out.format("data: [%d %f]\n", x, y);

得到如下结果:

data: [1 3.141593]

2、Formatter类:

在Java中所有新的格式化功能都由java.util.Formatter类处理。可将Formatter看做一个翻译器,将你的字符串翻译成需要的结果。

构造Formatter的时候,需要向其构造器传递一些信息,告诉最终的结果将向哪里输出:

public class Message{
private String username;
private Formatter f;
public Message(String username, Formatter f){
this.username = username;
this.f = f;
}
public void publishMsg(int hour, int minute){
f.format("%s says it is %d:%d\n", username, hour, minute);
}
public static void main(String[] args){
Message msg1 = new Message("Jason",
new Formatter(System.out)); // 传入System.out,信息输出到此
msg1.publishMsg(10, 12);

    Message msg2 = new Message("Jason",
            new Formatter(System.err)); // 当然,也可以传入System.err
    msg2.publishMsg(10, 13);

}

}

得到如下结果:

Jason says it is 10:12
Jason says it is 10:13

上例是向Formatter传入了PrintStream,Formatter的构造器经过重载可以接受多种输出目的地,如OutputStream和File(这里不作介绍)。

格式化说明符:

format字符串的格式化参数语法如下:

%[argument_index$][flags][width][.precision]conversion

argument_index$:argument_index 是一个十进制整数,用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用,第二个参数由 "2$" 引用,依此类推。

flags:可选 flags 是修改输出格式的字符集。有效标志集取决于转换类型。

width:控制一个域的最小值,默认情况下下是右对齐的,可以通过使用“-”标志来改变对其方向。

precision:精度,用于String时,表示输出字符的最大数量,用于浮点数时,表示小数部分要显示出来的 位数(默认是6位),多则舍入,少则补0,用于整数会触发异常。

conversion:转换格式,可选的格式有:

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

注意当使用b作为转换格式时,即Boolean,对于boolean基本类型或者Boolean对象,其转换结果是对应的true或false。但是对于其他类型的参数,只要该参数不为null,那么该转换的结果就永远都是true。0也会转换为true的,跟其他语言有所区别。所以将b运用于非布尔类型要注意。

下面是一个使用例子:

public class TableData {

// 格式化说明符的使用例子
private Formatter f = new Formatter(System.out);
public void printHead(){
    f.format("%-10s %5s %5s\\n", "username", "level", "score");
    f.format("%-10s %5s %5s\\n", "---", "---", "---");
}
public void printData(){
    f.format("%-10s %5d %5.2f\\n", "Jason", 1, 9.87654321);
    f.format("%-10s %5d %5.2f\\n", "arthinking", 2, 9.6512);
}

public static void main(String[] args){
    TableData tb = new TableData();
    tb.printHead();
    tb.printData();
}

}

输出如下内容:

username level score
--- --- ---
Jason 1 9.88
arthinking 2 9.65

下面的boolean转换都输出为true:

Formatter f = new Formatter(System.out);
f.format("boolean %b: ", "false");
f.format("boolean %b: ", 0);

3、String.format();

String.format()的内部,也是创建了一个Formatter对象,然后将你传入的参数转给该Formatter。是一个static方法,接受的参数和Formatter.format()一样,但是返回了一个String对象,如果你只需要使用format()方法一次时,String.format()方法使用起来很方便。

String formatStr = String.format("%#4X", 12);
System.out.println(formatStr);

上面的输出为:

0XC

4表示域的长度,#是flags,具体参考这里:

标志

下表总结了受支持的标志。y 表示该标志受指示参数类型支持。

标志

常规

字符

整数

浮点

日期/时间

说明

'-'

y

y

y

y

y

结果将是左对齐的。

'#'

y1

y3

y

结果应该使用依赖于转换类型的替换形式

'+'

y4

y

结果总是包括一个符号

'  '

y4

y

对于正值,结果中将包括一个前导空格

'0'

y

y

结果将用零来填充

','

y2

y5

结果将包括特定于语言环境的[组分隔符](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/text/DecimalFormatSymbols.html#getGroupingSeparator())

'('

y4

y5

结果将是用圆括号括起来的负数

1 取决于 [Formattable](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/util/Formattable.html "java.util 中的接口") 的定义。 2 只适用于 'd' 转换。 3 只适用于 'o''x' 和 'X' 转换。 4 对 [BigInteger](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/math/BigInteger.html "java.math 中的类") 应用 'd''o''x' 和 'X' 转换时,或者对 byte 及 [Byte](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/lang/Byte.html "java.lang 中的类")、short 及 [Short](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/lang/Short.html "java.lang 中的类")、int 及 [Integer](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/lang/Integer.html "java.lang 中的类")、long 及 [Long](file:///C:/Users/arthinking/AppData/Local/youdao/ynote/java/lang/Long.html "java.lang 中的类") 分别应用 'd' 转换时适用。 5 只适用于 'e''E''f''g' 和 'G' 转换。 任何未显式定义为标志的字符都是非法字符,并且都被保留,以供扩展使用。

更多说明参考JDK文档。

欢迎关注我的其它发布渠道

订阅IT宅
内功修炼
Java技术栈
Java架构杂谈是IT宅精品文章公众号,欢迎订阅:
📄 网络基础知识:两万字长文50+张趣图带你领悟网络编程的内功心法 📄 HTTP发展史:三万长文50+趣图带你领悟web编程的内功心法 📄 HTTP/1.1:可扩展,可靠性,请求应答,无状态,明文传输 📄 HTTP/1.1报文详解:Method,URI,URL,消息头,消息体,状态行 📄 HTTP常用请求头大揭秘 📄 HTTPS:网络安全攻坚战 📄 HTTP/2:网络安全传输的快车道 📄 HTTP/3:让传输效率再一次起飞 📄 高性能网络编程:图解Socket核心内幕以及五大IO模型 📄 高性能网络编程:三分钟短文快速了解信号驱动式IO 📄 高性能网络编程:彻底弄懂IO复用 - IO处理杀手锏,带您深入了解select,poll,epoll 📄 高性能网络编程:异步IO:新时代的IO处理利器 📄 高性能网络编程:网络编程范式 - 高性能服务器就这么回事 📄 高性能网络编程:性能追击 - 万字长文30+图揭秘8大主流服务器程序线程模型
📄 Java内存模型:如果有人给你撕逼Java内存模型,就把这些问题甩给他 📄 一文带你彻底理解同步和锁的本质(干货) 📄 AQS与并发包中锁的通用实现 📄 ReentrantLock介绍与使用 📄 ReentrantReadWriteLock介绍与使用 📄 ReentrantLock的Condition原理解析 📄 如何优雅的中断线程 📄 如何优雅的挂起线程 📄 图解几个好玩的并发辅助工具类 📄 图解BlockingQueue阻塞队列
📄 消息队列那么多,为什么建议深入了解下RabbitMQ? 📄 高并发异步解耦利器:RocketMQ究竟强在哪里? 📄 Kafka必知必会18问:30+图带您看透Kafka
📄 洞悉MySQL底层架构:游走在缓冲与磁盘之间 📄 SQL运行内幕:从执行原理看调优的本质 📄 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法