Ръководство за java.util.Formatter

1. Общ преглед

В тази статия ще обсъдим форматирането на String в Java с помощта на класа java.util.Formatter , който осигурява поддръжка за оправдание и подравняване на оформлението.

2. Как да използвам форматиращия инструмент

Помните ли printf на C ? Форматирането на низ в Java се чувства много подобно.

Методът format () на Formatter се излага чрез статичен метод от класа String . Този метод приема низ от шаблон и списък с аргументи за попълване на шаблона с:

String greetings = String.format( "Hello Folks, welcome to %s !", "Baeldung");

Полученият низ е:

"Hello Folks, welcome to Baeldung !"

Шаблонът е низ, който съдържа статичен текст и един или повече спецификатори на формат, които указват кой аргумент трябва да бъде поставен в конкретната позиция.

В този случай има спецификатор на един формат % s , който се заменя със съответния аргумент.

3. Спецификатори на формата

3.1. Общ синтаксис

Синтаксисът на спецификаторите на формат за Общ, Символен и Числов тип е:

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

Спецификаторите аргумент_индекс, флаг, ширина и точност не са задължителни.

  • argument_index част е цяло число i - указващо, че тук трябва да се използва i-тият аргумент от списъка с аргументи
  • flags е набор от символи, използвани за промяна на изходния формат
  • width е положително цяло число, което показва минималния брой символи, които трябва да бъдат записани в изхода
  • точност е цяло число, обикновено използвано за ограничаване на броя на знаците, чието специфично поведение зависи от преобразуването
  • е задължителната част. Това е знак, указващ как трябва да бъде форматиран аргументът. Наборът от валидни преобразувания за даден аргумент зависи от типа данни на аргумента

В нашия пример по-горе, ако искаме да посочим изрично номера на аргумент, можем да го напишем, използвайки индекси на аргументи 1 $ и 2 $ .

И двете са съответно първият и вторият аргумент:

String greetings = String.format( "Hello %2$s, welcome to %1$s !", "Baeldung", "Folks");

3.2. За дата / час Представителство

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

Отново аргументът_индекс, флагове и ширина не са задължителни.

Нека вземем пример, за да разберем това:

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

Тук за всеки спецификатор на формат ще бъде използван 1-вият аргумент, следователно 1 $ . Тук, ако пропуснем аргумента_индекс за втория и третия спецификатор на формат, той се опитва да намери 3 аргумента, но трябва да използваме един и същ аргумент за всички 3 спецификатора на формат.

Така че, добре е, ако не посочим аргумент _index за първия, но трябва да го посочим за другите два.

В знаме тук се състои от два символа. Където първият знак винаги е „t“ или „T“ . Вторият знак зависи от това каква част от календара трябва да се покаже.

В нашия пример, първите спецификатори на формат tm , посочват месеца, форматиран като две цифри, te посочва деня на месеца и tY посочва Годината, форматиран като четири цифри.

3.3. Форматиране на спецификатори без аргументи

%[flags][width]conversion

Незадължителните флагове и ширина са същите, както са дефинирани в горните раздели.

Необходимото преобразуване е символ или низ, показващ съдържание, което трябва да се вмъкне в изхода. Понастоящем само '%' и нов ред 'n' могат да бъдат отпечатани с помощта на това:

@Test public void whenNoArguments_thenExpected() { String s = String.format("John scored 90%% in Fall semester"); assertEquals("John scored 90% in Fall semester", s); } 

Вътре във формат () , ако искаме да отпечатаме „%“ - трябва да избягаме от него, като използваме „%%“ .

4. Преобразувания

Нека сега да разгледаме всеки детайл от синтаксиса на Format Specifier, започвайки с преобразуване . Обърнете внимание, че можете да намерите всички подробности в javadocs на Formatter .

Както забелязахме в горните примери, частта за преобразуване се изисква във всички спецификатори на формата и може да бъде разделена на няколко категории.

Нека да разгледаме всеки един, като вземем примери.

4.1. Общ

Използва се за всеки тип аргумент. Общите реализации са:

  1. 'b' или 'B' - за булеви стойности
  2. 'h' или 'H' - за HashCode
  3. 's' или 'S' - за String , ако е null , той отпечатва „null“, в противен случай arg.toString ()

Сега ще се опитаме да покажем булеви и низови стойности, като използваме съответните преобразувания:

@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. Характер

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.

It can be written as ‘c’ or ’C’ based on the case we want.

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

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:

  1. ‘d' – for decimal number
  2. ‘o' – for octal number
  3. ‘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

Used for Java floating-point types: float, Float, double, Double, and BigDecimal

  1. ‘e' or ‘E'formatted as a decimal number in computerized scientific notation
  2. ‘f'formatted as a decimal number
  3. ‘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

  • 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

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.

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

For general conversions, precision is just the maximum number of characters to be written to the output. Whereas, f or the floating-point conversions the precision is the number of digits after the radix point.

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

As mentioned previously, theargument_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.

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:

@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 %
    

8. Other Ways of Using 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.

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.

Let's see an example of using it with an Appendable. We can use it with others in the same way.

8.1. Using Formatter With Appendable

Let's create a StringBuilder instance sb, and create a Formatter using it. Then we'll invoke format() to format a 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

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.

As usual, the code for the examples we saw can be found over on Github.