String.format方法,Java常用类库——Formatter

时间:2023-01-14 18:38:46


在进行字符串操作时很多时候是想得到适合当前环境阅读的格式,比如时间:

Tue Feb 23 11:35:54 CST 2016这种格式是不适宜阅读的。如格式化为2016-2-2311:35:54。

上面两句的输出代码为:

System.out.println(“现在时间:” + new Date());
System.out.println(String.format("现在时间:%tF %tT", new Date() , new Date()));

使用的就是String#format方法对字符串进行格式化。

Formatter类联机中文文档http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/Formatter.html

Formatter示例代码中给出了65个示例代码,介绍了格式化的具体使用 http://www.javased.com/index.php?api=java.util.Formatter

在上面的代码中发现%tF以及%tT被待转换字符串替换成特定的格式。%tF、%tT可以理解为占位符,当解析到此种标志时,就会使用待转换的值代替这个位置。类似于s

hql中的(:arg)。%tF分为三个部分,每个字符为一个部分%是标志符号,t是类别符号,表示是时间类的转换,F是具体的转换格式,F表示ISO 8601 格式的完整日期,被格式化为"2016-2-23"形式

转换

转换可分为以下几类:

  1. 常规 - 可应用于任何参数类型
  2. 字符 - 可应用于表示 Unicode 字符的基本类型:charCharacterbyteByteshortShort。当Character.isValidCodePoint(int) 返回true 时,可将此转换应用于intInteger 类型
  3. 数值
    1. 整数 - 可应用于 Java 的整数类型:byteByteshortShortintIntegerlongLongBigInteger
    2. 浮点 - 可用于 Java 的浮点类型:floatFloatdoubleDoubleBigDecimal
  4. 日期/时间 - 可应用于 Java 的、能够对日期或时间进行编码的类型:longLongCalendarDate
  5. 百分比 - 产生字面值 '%' ('\u0025')
  6. 行分隔符 - 产生特定于平台的行分隔符

package com.gos.java.standard;
import java.util.Date;

public class StringFormatTest1 {

public static void main(String[] args) {
//1.常规转换
/**
\u0062将生成 "true" 或 "false",由Boolean.toString(boolean) 返回。如果参数为 null,则结果为 "false"。如果参数是一个 boolean 值或 Boolean,那么结果是由 String.valueOf() 返回的字符串。否则结果为 "true"。如果给出 '#' 标志,则将抛出 FormatFlagsConversionMismatchException。
B\u0042b的大写形式。
h\u0068生成一个表示对象的哈希码值的字符串。如果参数 arg 为 null,则结果为 "null"。否则,结果为调用 Integer.toHexString(arg.hashCode()) 得到的结果。如果给出 '#' 标志,则将抛出 FormatFlagsConversionMismatchException。
H\u0048h的大写形式。
s\u0073生成一个字符串。
S\u0053s的大写形式。
*/
System.out.println(String.format(NO(new Throwable()) + "结果为 :%b", false));
System.out.println(String.format(NO(new Throwable()) + "结果为 :%\u0062", false));
System.out.println(String.format(NO(new Throwable()) + "结果的大写形式为 :%B", false));
String str = new String("一个String对象");
System.out.println(String.format(NO(new Throwable()) + "对象[%s]的hash码为:%h", str , str));
System.out.println(String.format(NO(new Throwable()) + "对象[%S]的hash码的大写形式为:%H", str , str));
//2.字符
/**
此转换可应用于 char 和 Character。它还可应用于类型 byte、Byte、short 和 Short、 int 和 Integer。当 Character.isValidCodePoint(int) 返回 true 时,此转换也可应用于 int 和 Integer。如果返回 false,则将抛出 IllegalFormatCodePointException。
c\u0063将参数格式化为 Unicode Character Representation 中描述的 Unicode 字符。在该参数表示增补字符的情况下,它可能是多个 16 位 char。 如果给出 '#' 标志,则将抛出 FormatFlagsConversionMismatchException。
C\u0043c的大写形式。
*/
System.out.println(String.format(NO(new Throwable()) + "字符:%c%c" , 'a' , 'A'));
System.out.println(String.format(NO(new Throwable()) + "字符:%C" , 'A'));
//3.数值
/**
d将参数转换成十进制整数。
o转换成八进制数。
x转换成十六进制数。
Xx的大写形式。
e要求使用科学记数法来格式化输出。
Ee的大写形式。
g常规科学记数形式。
Gg的大写形式。
f使用十进制形式来格式化输出。
a要求将输出格式化为十六进制指数形式。
Aa的大写形式。
*/
System.out.println(String.format(NO(new Throwable()) + "百分比:%d%%", 85));
System.out.println(String.format(NO(new Throwable()) + "8转换成八进制为:%o", 8));
System.out.println(String.format(NO(new Throwable()) + "22转换成十六进制为:%x", 22));
System.out.println(String.format(NO(new Throwable()) + "97.1的科学计数表示:%e", 97.1));
System.out.println(String.format(NO(new Throwable()) + "97.1的科学计数表示:%g", 97.1));
System.out.println(String.format(NO(new Throwable()) + "97.1使用%%%s表示:%f", "f" , 97.1));
System.out.println(String.format(NO(new Throwable()) + "97.1使用%%%s表示:%a", "a" , 97.1));
System.out.println(String.format(NO(new Throwable()) + "97.124保留两位小数%.2f%%", 97.124));
System.out.println(String.format(NO(new Throwable()) + "97.125保留两位小数%.2f%%", 97.125));
System.out.println(String.format(NO(new Throwable()) + "97.126保留两位小数%.2f%%", 97.126));
//4.1时间
/**
H\u004824 小时制的小时,被格式化为必要时带前导零的两位数,即 00 - 23。00 对应午夜。
I\u004912 小时制的小时,被格式化为必要时带前导零的两位数,即 01 - 12。01 对应于 1 点钟(上午或下午)。
k\u006b24 小时制的小时,即 0 - 23。0 对应于午夜。
l\u006c12 小时制的小时,即 1 - 12。1 对应于上午或下午的一点钟。
M\u004d小时中的分钟,被格式化为必要时带前导零的两位数,即 00 - 59。
S\u0053分钟中的秒,被格式化为必要时带前导零的两位数,即 00 - 60("60" 是支持闰秒所需的一个特殊值)。
L\u004c秒中的毫秒,被格式化为必要时带前导零的三位数,即 000 - 999。
N\u004e秒中的毫微秒,被格式化为必要时带前导零的九位数,即 000000000 - 999999999。此值的精度受底层操作系统或硬件解析的限制。
p\u0070特定于语言环境的上午或下午标记以小写形式表示,例如 "am" 或 "pm"。使用转换前缀 'T' 可以强行将此输出转换为大写形式。(注意,'p' 产生的输出是小写的。而 GNU date 和 POSIX strftime(3c) 产生的输出是大写的。)
z\u007a相对于 GMT 的 RFC 822 格式的数字时区偏移量,例如 -0800
Z\u005a表示时区的缩写形式的字符串。
s\u0073自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的秒数,也就是 Long.MIN_VALUE/1000 与 Long.MAX_VALUE/1000 之间的差值。
Q\u004f自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的毫秒数,即 Long.MIN_VALUE 与 Long.MAX_VALUE 之间的差值。此值的精度受底层操作系统或硬件解析的限制。
*/
Date date = new Date();
System.out.println(String.format(NO(new Throwable()) + "带前导零的24 小时制的小时:%tH" , date));
System.out.println(String.format(NO(new Throwable()) + "带前导零的12 小时制的小时:%tI" , date));
System.out.println(String.format(NO(new Throwable()) + "不带前导零的24 小时制的小时:%tk" , date));
System.out.println(String.format(NO(new Throwable()) + "不带前导零的24 小时制的小时:%tl" , date));
System.out.println(String.format(NO(new Throwable()) + "分钟:%tM" , date));
System.out.println(String.format(NO(new Throwable()) + "秒:%tS" , date));
System.out.println(String.format(NO(new Throwable()) + "毫秒:%tL" , date));
System.out.println(String.format(NO(new Throwable()) + "毫微秒:%tN" , date));
System.out.println(String.format(NO(new Throwable()) + "上午or下午:%tp" , date));
System.out.println(String.format(NO(new Throwable()) + "时区:%tz" , date));
System.out.println(String.format(NO(new Throwable()) + "自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的秒数:%ts" , date));
System.out.println(String.format(NO(new Throwable()) + "自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的毫秒数:%tQ" , date));
//4.2日期
/**
'B' '\u0042' 特定于语言环境的完整月份名称,例如 "January" 和 "February"。
'b' '\u0062' 特定于语言环境的月份简称,例如 "Jan" 和 "Feb"。
'h' '\u0068' 与 'b' 相同。
'A' '\u0041' 特定于语言环境的星期几的全称,例如 "Sunday" 和 "Monday"
'a' '\u0061' 特定于语言环境的星期几的简称,例如 "Sun" 和 "Mon"
'C' '\u0043' 除以 100 的四位数表示的年份,被格式化为必要时带前导零的两位数,即 00 - 99
'Y' '\u0059' 年份,被格式化为必要时带前导零的四位数(至少),例如 0092 等于格里高利历的 92 CE。
'y' '\u0079' 年份的最后两位数,被格式化为必要时带前导零的两位数,即 00 - 99。
'j' '\u006a' 一年中的天数,被格式化为必要时带前导零的三位数,例如,对于格里高利历是 001 - 366。001 对应于一年中的第一天。
'm' '\u006d' 月份,被格式化为必要时带前导零的两位数,即 01 - 13,其中 "01" 是一年的第一个月,("13" 是支持阴历所需的一个特殊值)。
'd' '\u0064' 一个月中的天数,被格式化为必要时带前导零的两位数,即 01 - 31,其中 "01" 是一个月的第一天。
'e' '\u0065' 一个月中的天数,被格式化为两位数,即 1 - 31,其中 "1" 是一个月中的第一天。
*/
System.out.println(String.format(NO(new Throwable()) + "月份名称:%tB" , date));
System.out.println(String.format(NO(new Throwable()) + "月份简称:%tb" , date));
System.out.println(String.format(NO(new Throwable()) + "星期几的全称:%tA" , date));
System.out.println(String.format(NO(new Throwable()) + "星期几的简称:%ta" , date));
System.out.println(String.format(NO(new Throwable()) + "世纪century-1:%tC" , date));
System.out.println(String.format(NO(new Throwable()) + "年份:%tY" , date));
System.out.println(String.format(NO(new Throwable()) + "年份的最后两位数:%ty" , date));
System.out.println(String.format(NO(new Throwable()) + "当天是该年中的第几天:%tj" , date));
System.out.println(String.format(NO(new Throwable()) + "月份,被格式化为必要时带前导零的两位数:%tm" , date));
System.out.println(String.format(NO(new Throwable()) + "一个月中的天数带前导零的两位数:%td" , date));
System.out.println(String.format(NO(new Throwable()) + "一个月中的天数不带前导零的两位数:%te" , date));
//4.3时间日期组合
/**
'R' '\u0052' 24 小时制的时间,被格式化为 "%tH:%tM"
'T' '\u0054' 24 小时制的时间,被格式化为 "%tH:%tM:%tS"。
'r' '\u0072' 12 小时制的时间,被格式化为 "%tI:%tM:%tS %Tp"。上午或下午标记 ('%Tp') 的位置可能与地区有关。
'D' '\u0044' 日期,被格式化为 "%tm/%td/%ty"。
'F' '\u0046' ISO 8601 格式的完整日期,被格式化为 "%tY-%tm-%td"。
'c' '\u0063' 日期和时间,被格式化为 "%ta %tb %td %tT %tZ %tY",例如 "Sun Jul 20 16:17:00 EDT 1969"。
*/
System.out.println(String.format(NO(new Throwable()) + "24 小时制的时间tH:tM:%tR" , date));
System.out.println(String.format(NO(new Throwable()) + "24 小时制的时间tH:tM:tS:%tT" , date));
System.out.println(String.format(NO(new Throwable()) + "12 小时制的时间tI:tM:tS TP:%tr" , date));
System.out.println(String.format(NO(new Throwable()) + "日期tm/td/ty:%tD" , date));
System.out.println(String.format(NO(new Throwable()) + "日期tY-tm-td:%tF" , date));
System.out.println(String.format(NO(new Throwable()) + "日期和时间ta tb td tT tZ tY:%tc" , date));
//5.其他
/**
* %输出百分号
* n行分隔符,换行
*/
System.out.println(String.format(NO(new Throwable()) + "百分号%%,换行开始%n%n换行结束。"));
//6.参数索引
/**
格式说明符可以通过三种方式引用参数:
①显式索引 是在格式说明符中包含参数索引时使用。参数索引是一个十进制整数,用于指示参数在参数列表中的位置。第一个参数由 "1$" 引用,第二个参数由 "2$" 引用,依此类推。可以多次引用任何一个参数。
②相对索引 是在格式说明符中包含 '<' ('\u003c') 标志时使用,该标志将导致重用以前格式说明符的参数。如果不存在以前的参数,则抛出 MissingFormatArgumentException。
③ 普通索引 在格式说明符中既不包含参数索引也不包含 '<' 标志时使用。每个使用普通索引的格式说明符都分配了一个连续隐式索引,分配在独立于显式索引或相对索引使用的参数列表中。
可能有一个使用所有索引形式的格式字符串,例如:
参数的最大数量受到 Java Machine Specification 定义的 Java 数组 的最大维数的限制。如果参数索引与可用参数不对应,则抛出 MissingFormatArgumentException。
如果参数多于格式说明符,则忽略额外的参数。
除非另行指定,否则向此类中的任何方法或构造方法传递 null 参数都将抛出 NullPointerException。
*/
System.out.println(String.format(NO(new Throwable()) + "%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s", "a", "b", "c", "d"));
System.out.println(String.format(NO(new Throwable()) + "%s %s %<s %<s", "a", "b", "c", "d"));
System.out.println(String.format(NO(new Throwable()) + "%s %s %s %s", "a", "b", "c", "d"));
System.out.println(String.format(NO(new Throwable()) + "%2$s %s %<s %s", "a", "b", "c", "d"));
//TODO 输出对齐?
//DecimalFormatSymbols df = new DecimalFormatSymbols();
//System.out.println(df.getZeroDigit());
//df.setZeroDigit('零');
//System.out.println(df.getZeroDigit());
}
public static String NO(Throwable t){
StackTraceElement[] stacks = t.getStackTrace();
return "[行号" + stacks[0].getLineNumber() + "]输出:";
}
}

代码输出:

[行号16]输出:结果为 :false
[行号17]输出:结果为 :false
[行号18]输出:结果的大写形式为 :FALSE
[行号20]输出:对象[一个String对象]的hash码为:fc67a9a3
[行号21]输出:对象[一个STRING对象]的hash码的大写形式为:FC67A9A3
[行号28]输出:字符:aA
[行号29]输出:字符:A
[行号44]输出:百分比:85%
[行号45]输出:8转换成八进制为:10
[行号46]输出:22转换成十六进制为:16
[行号47]输出:97.1的科学计数表示:9.710000e+01
[行号48]输出:97.1的科学计数表示:97.1000
[行号49]输出:97.1使用%f表示:97.100000
[行号50]输出:97.1使用%a表示:0x1.8466666666666p6
[行号51]输出:97.124保留两位小数97.12%
[行号52]输出:97.125保留两位小数97.13%
[行号53]输出:97.126保留两位小数97.13%
[行号71]输出:带前导零的24 小时制的小时:11
[行号72]输出:带前导零的12 小时制的小时:11
[行号73]输出:不带前导零的24 小时制的小时:11
[行号74]输出:不带前导零的24 小时制的小时:11
[行号75]输出:分钟:26
[行号76]输出:秒:57
[行号77]输出:毫秒:683
[行号78]输出:毫微秒:683000000
[行号79]输出:上午or下午:上午
[行号80]输出:时区:+0800
[行号81]输出:自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的秒数:1456284417
[行号82]输出:自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的毫秒数:1456284417683
[行号98]输出:月份名称:二月
[行号99]输出:月份简称:二月
[行号100]输出:星期几的全称:星期三
[行号101]输出:星期几的简称:星期三
[行号102]输出:世纪century-1:20
[行号103]输出:年份:2016
[行号104]输出:年份的最后两位数:16
[行号105]输出:当天是该年中的第几天:055
[行号106]输出:月份,被格式化为必要时带前导零的两位数:02
[行号107]输出:一个月中的天数带前导零的两位数:24
[行号108]输出:一个月中的天数不带前导零的两位数:24
[行号118]输出:24 小时制的时间tH:tM:11:26
[行号119]输出:24 小时制的时间tH:tM:tS:11:26:57
[行号120]输出:12 小时制的时间tI:tM:tS TP:11:26:57 上午
[行号121]输出:日期tm/td/ty:02/24/16
[行号122]输出:日期tY-tm-td:2016-02-24
[行号123]输出:日期和时间ta tb td tT tZ tY:星期三 二月 24 11:26:57 CST 2016
[行号129]输出:百分号%,换行开始

换行结束。
[行号141]输出:d c b a d c b a
[行号142]输出:a b b b
[行号143]输出:a b c d
[行号144]输出:b a a b