1. Overview
1.概述
In this article, we’ll discuss the String formatting in Java using the java.util.Formatter class, which provides support for the layout justification and alignment.
在这篇文章中,我们将使用java.util.Formatter类来讨论Java中的String格式化,该类提供了对布局公正和对齐的支持。
2. How to Use the Formatter
2.如何使用格式化
Remember C’s printf? Formatting a String in Java feels very similar.
还记得C语言的printf吗?在Java中对一个字符串进行格式化,感觉非常相似。
The format() method of the Formatter is exposed via a static method from the String class. This method accepts a template String and a list of arguments to populate the template with:
Format()方法是通过String类中的一个静态方法暴露的。该方法接受一个模板String和一个参数列表,以填充该模板:。
String greetings = String.format(
"Hello Folks, welcome to %s !",
"Baeldung");
The resulting String is:
产生的String是。
"Hello Folks, welcome to Baeldung !"
A template is a String that contains some static text and one or more format specifiers, which indicate which argument is to be placed at the particular position.
模板是一个String,它包含一些静态文本和一个或多个格式指定器,这些指定器表明哪个参数将被放在特定的位置。
In this case, there’s a single format specifier %s, which gets replaced by the corresponding argument.
在这种情况下,有一个单一的格式指定符%s,它被相应的参数所取代。
3. Format Specifiers
3.格式指定器
3.1. General Syntax
3.1.一般语法
The syntax of format specifiers for General, Character, and Numeric type is:
普通、字符、和数字类型的格式指定器的语法是:
%[argument_index$][flags][width][.precision]conversion
Specifiers argument_index, flag, width, and precision are optional.
规范argument_index, flag, width, 和precision是可选的。
- argument_index part is an integer i – indicating that the ith argument from the argument list should be used here
- flags is a set of characters used for modifying the output format
- width is a positive integer which indicates the minimum number of characters to be written to the output
- precision is an integer usually used to restrict the number of characters, whose specific behavior depends on the conversion
- is the mandatory part. It’s a character indicating how the argument should be formatted. The set of valid conversions for a given argument depends on the argument’s data type
In our example above, if we want to specify the number of an argument explicitly, we can write it using 1$ and 2$ argument indices.
在我们上面的例子中,如果我们想明确地指定一个参数的数量,我们可以用1$和2$参数索引来写它。
Both these being the first and second argument respectively:
这两点分别是第一和第二参数。
String greetings = String.format(
"Hello %2$s, welcome to %1$s !",
"Baeldung",
"Folks");
3.2. For Date/Time Representation
3.2.对于日期/时间表示
%[argument_index$][flags][width]conversion
Again the argument_index, flags, and width are optional.
另外,argument_index、flags和width是可选的。
Let’s take an example to understand this:
让我们举个例子来理解这一点。
@Test
public void whenFormatSpecifierForCalendar_thenGotExpected() {
Calendar c = new GregorianCalendar(2017, 11, 10);
String s = String.format(
"The date is: %tm %1$te,%1$tY", c);
assertEquals("The date is: 12 10,2017", s);
}
Here, for every format specifier, the 1st argument will be used, hence 1$. Here if we skip the argument_index for 2nd and 3rd format specifier, it tries to find 3 arguments, but we need to use the same argument for all 3 format specifiers.
在这里,对于每个格式指定器,第一个参数将被使用,因此1$。在这里,如果我们跳过第2和第3个格式指定器的argument_index ,它将试图找到3个参数,但我们需要对所有3个格式指定器使用同一个参数。
So, it’s ok if we don’t specify argument _index for the first one, but we need to specify it for the other two.
所以,如果我们不为第一个参数指定argument _index 是可以的,但是我们需要为另外两个参数指定。
The flag here is made up of two characters. Where the first character is always a ‘t’ or ‘T’. The second character depends on what part of Calendar is to be displayed.
这里的标志是由两个字符组成的。其中第一个字符总是一个‘t’或‘T’。第二个字符取决于要显示Calendar的哪一部分。
In our example, the first format specifiers tm, indicates month formatted as two digits, te indicates the day of the month and tY indicated Year formatted as four digits.
在我们的例子中,第一个格式指定符tm,表示月份,格式为两位数,te表示月份的一天,tY表示年份,格式为四位数。
3.3. Format Specifiers Without Arguments
3.3.没有参数的格式指定器
%[flags][width]conversion
The optional flags and width are the same as defined in above sections.
可选的flags和width与上述章节中的定义相同。
The required conversion is a character or String indicating content to be inserted in the output. Currently, only the ‘%’ and newline ‘n’ can be printed using this:
所需的转换是一个字符或字符串,表示要在输出中插入的内容。目前,只有 ‘%’和换行 ‘n’可以使用这个打印:
@Test
public void whenNoArguments_thenExpected() {
String s = String.format("John scored 90%% in Fall semester");
assertEquals("John scored 90% in Fall semester", s);
}
Inside format(), if we want to print ‘%’ – we need to escape it by using ‘%%’.
在format()里面,如果我们想打印‘%’–我们需要用‘%’来转义。
4. Conversions
4.转换
Let’s now dig into every detail of the Format Specifier syntax, starting with a conversion. Note that you can find all the details in the Formatter javadocs.
现在让我们从转换开始,挖掘格式指定器语法的每个细节。请注意,你可以在Formatter javadocs中找到所有的细节。。
As we noticed in the above examples, conversion part is required in all format specifiers, and it can be divided into several categories.
正如我们在上面的例子中注意到的,转换部分在所有的格式指定器中都是需要的,它可以分为几类。
Let’s take a look at each one by taking examples.
让我们通过举例来看看每个人的情况。
4.1. General
4.1 总则
Used for any argument type. The general conversions are:
用于任何参数类型。一般的转换方法是:
- ‘b’ or ‘B’ – for Boolean values
- ‘h’ or ‘H’ – for HashCode
- ‘s’ or ‘S’ – for String, if null, it prints “null”, else arg.toString()
We’ll now try to display boolean and String values, using the corresponding conversions:
我们现在将尝试显示boolean和String值,使用相应的转换:。
@Test
public void givenString_whenGeneralConversion_thenConvertedString() {
String s = String.format("The correct answer is %s", false);
assertEquals("The correct answer is false", s);
s = String.format("The correct answer is %b", null);
assertEquals("The correct answer is false", s);
s = String.format("The correct answer is %B", true);
assertEquals("The correct answer is TRUE", s);
}
4.2. Character
4.2.性格
Used for the basic types which represent Unicode characters: char, Character, byte, Byte, short, and Short. This conversion can also be used for the types int and Integer when the Character.isValidCodePoint(int) returns true for them.
用于表示Unicode字符的基本类型。char、Character、byte、Byte、short、和Short。当Character.isValidCodePoint(int)返回true时,这种转换也可以用于int和Integer类型。
It can be written as ‘c’ or ’C’ based on the case we want.
根据我们想要的情况,它可以写成‘c’或者‘C’。
Let’s try to print some characters:
让我们试着打印一些字符。
@Test
public void givenString_whenCharConversion_thenConvertedString() {
String s = String.format("The correct answer is %c", 'a');
assertEquals("The correct answer is a", s);
s = String.format("The correct answer is %c", null);
assertEquals("The correct answer is null", s);
s = String.format("The correct answer is %C", 'b');
assertEquals("The correct answer is B", s);
s = String.format("The valid unicode character: %c", 0x0400);
assertTrue(Character.isValidCodePoint(0x0400));
assertEquals("The valid unicode character: Ѐ", s);
}
Let’s take one more example of an invalid code point:
让我们再举一个无效代码点的例子。
@Test(expected = IllegalFormatCodePointException.class)
public void whenIllegalCodePointForConversion_thenError() {
String s = String.format("The valid unicode character: %c", 0x11FFFF);
assertFalse(Character.isValidCodePoint(0x11FFFF));
assertEquals("The valid unicode character: Ā", s);
}
4.3. Numeric – Integral
4.3.数字 – 综合
These are used for Java integral types: byte, Byte, short, Short, int and Integer, long, Long, and BigInteger. There are three conversions in this category:
这些是用于Java的积分类型。byte, Byte, short, Short, int和Integer, long, Long,和BigInteger。该类别中有三种转换。
- ‘d’ – for decimal number
- ‘o’ – for octal number
- ‘X’ or ‘x’ – for hexadecimal number
Let’s try to print each of these:
让我们试着把这些东西一一打印出来。
@Test
public void whenNumericIntegralConversion_thenConvertedString() {
String s = String.format("The number 25 in decimal = %d", 25);
assertEquals("The number 25 in decimal = 25", s);
s = String.format("The number 25 in octal = %o", 25);
assertEquals("The number 25 in octal = 31", s);
s = String.format("The number 25 in hexadecimal = %x", 25);
assertEquals("The number 25 in hexadecimal = 19", s);
}
4.4. Numeric – Floating Point
4.4.数值–浮点
Used for Java floating-point types: float, Float, double, Double, and BigDecimal
用于Java浮点类型。float, Float, double, Double,和BigDecimal。
- ‘e’ or ‘E’ – formatted as a decimal number in computerized scientific notation
- ‘f’ – formatted as a decimal number
- ‘g’ or ‘G’ – based on the precision value after rounding, this conversion formats into computerized scientific notation or decimal format
Let’s try to print the floating point numbers:
让我们试着打印浮点数字。
@Test
public void whenNumericFloatingConversion_thenConvertedString() {
String s = String.format(
"The computerized scientific format of 10000.00 "
+ "= %e", 10000.00);
assertEquals(
"The computerized scientific format of 10000.00 = 1.000000e+04", s);
String s2 = String.format("The decimal format of 10.019 = %f", 10.019);
assertEquals("The decimal format of 10.019 = 10.019000", s2);
}
4.5. Other Conversions
4.5.其他转换
- Date/Time – for Java types which are capable of encoding a date or time: long, Long, Calendar, Date and TemporalAccessor. For this, we need to use prefixed ‘t’ or ‘T’, as we saw earlier
- Percent – prints a literal ‘%’ (‘\u0025′)
- Line Separator – prints a platform-specific line separator
Let’s have a look at a simple example:
让我们看一下一个简单的例子。
@Test
public void whenLineSeparatorConversion_thenConvertedString() {
String s = String.format("First Line %nSecond Line");
assertEquals("First Line \n" + "Second Line", s);
}
5. Flags
5 旗子
Flags, in general, are used to format the output. Whereas in case of date and time, they are used to specify which part of the date is to be displayed, as we saw in the Section 4 example.
标志,一般来说,是用来格式化输出的。而在日期和时间的情况下,它们被用来指定日期的哪一部分被显示,正如我们在第4节的例子中所看到的。
A number of flags are available, a list of which can be found in the documentation.
有许多标志可用,其清单可在文档中找到。
Let’s see a flag example to understand it’s usage. ‘-‘ is used to format the output as left justified:
让我们看一个标志的例子来了解它的用法。‘-‘是用来将输出格式化为左对齐的。
@Test
public void whenSpecifyFlag_thenGotFormattedString() {
String s = String.format("Without left justified flag: %5d", 25);
assertEquals("Without left justified flag: 25", s);
s = String.format("With left justified flag: %-5d", 25);
assertEquals("With left justified flag: 25 ", s);
}
6. Precision
6.精度
For general conversions, precision is just the maximum number of characters to be written to the output. Whereas, for the floating-point conversions the precision is the number of digits after the radix point.
对于一般的转换,精度只是要写入输出的最大字符数。而f或浮点转换时,精度是弧度点之后的数字。
The first statement is an example of precision with floating-point numbers, and the second one with general conversions:
第一条语句是用浮点数进行精确计算的例子,第二条语句是用一般转换的例子。
@Test
public void whenSpecifyPrecision_thenGotExpected() {
String s = String.format(
"Output of 25.09878 with Precision 2: %.2f", 25.09878);
assertEquals("Output of 25.09878 with Precision 2: 25.10", s);
String s2 = String.format(
"Output of general conversion type with Precision 2: %.2b", true);
assertEquals("Output of general conversion type with Precision 2: tr", s2);
}
7. Argument Index
7.论点索引
As mentioned previously, the argument_index is an integer that indicates the position of the argument in the argument list. 1$ indicates the first argument, 2$ the second argument, and so on.
如前所述, argument_index是一个整数,表示参数在参数列表中的位置。1$表示第一个参数,2$表示第二个参数,以此类推。
Also, there is another way to reference arguments by position, by using the ‘<‘ (‘\u003c’) flag, which means the argument from the previous format specifier will be re-used. For example, these two statements would produce the identical output:
此外,还有一种方法可以通过位置来引用参数,即使用 ‘<‘ (‘\u003c’)标志,这意味着前一个格式指定器的参数将被重新使用。例如,这两条语句将产生相同的输出:
@Test
public void whenSpecifyArgumentIndex_thenGotExpected() {
Calendar c = Calendar.getInstance();
String s = String.format("The date is: %tm %1$te,%1$tY", c);
assertEquals("The date is: 12 10,2017", s);
s = String.format("The date is: %tm %<te,%<tY", c);
assertEquals("The date is: 12 10,2017", s);
}
8. Other Ways of Using Formatter
8.使用Formatter的其他方法
Till now we saw the use of format() method of the Formatter class. We can also create a Formatter instance, and use that to invoke the format() method.
到目前为止,我们看到了format() 方法在Formatter 类中的应用。我们也可以创建一个Formatter实例,并使用它来调用format() 方法。
We can create an instance by passing in an Appendable, OutputStream, File or file name. Based on this, the formatted String is stored in an Appendable, OutputStream, File respectively.
我们可以通过传入Appendable、OutputStream、File或文件名创建一个实例。在此基础上,格式化的String将分别存储在Appendable、OutputStream、File中。
Let’s see an example of using it with an Appendable. We can use it with others in the same way.
让我们看一个用Appendable使用它的例子。我们可以以同样的方式将它用于其他的东西。
8.1. Using Formatter With Appendable
8.1.使用Formatter与Appendable
Let’s create a StringBuilder instance sb, and create a Formatter using it. Then we’ll invoke format() to format a String:
让我们创建一个StringBuilder实例sb,并使用它创建一个Formatter。然后我们将调用format() 来格式化一个String。
@Test
public void whenCreateFormatter_thenFormatterWithAppendable() {
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb);
formatter.format("I am writting to a %s Instance.", sb.getClass());
assertEquals(
"I am writting to a class java.lang.StringBuilder Instance.",
sb.toString());
}
9. Conclusion
9.结论
In this article, we saw the formatting facilities provided by the java.util.Formatter class. We saw various syntax that can be used to format the String and the conversion types that can be used for different data types.
在这篇文章中,我们看到了由java.util.Formatter类提供的格式化设施。我们看到了可用于格式化String的各种语法以及可用于不同数据类型的转换类型。
As usual, the code for the examples we saw can be found over on Github.
像往常一样,我们看到的例子的代码可以在Github上找到over。