Printf-Style Output Formatting in Java

Learn to use various methods for printf-style string formatting in Java. Java language adapts this formatting from the C language, but Java adds some additional type safety and convenience features such as variable-length argument lists and autoboxing of primitive types.

1. Formatter.format() is at the Heart of Text Formatting

The main method at the heart for text formatting is the java.util.Formatter class and its format() method. The format() utilizes special format strings/patterns embedded into the text to tell the formatting engine where to place the method arguments. To keep things simpler, it accepts variable-length argument lists.

This method takes an optional Locale instance for locale-specific formatting.

format(String, arg1, arg2, arg3...)
format(Locale, String, arg1, arg2, arg3...)

Here are a few more methods that utilize this method internally such as:

  • String.format(): helps in getting formatted strings.
  • PrintStream.printf(): helps in writing formatted output to the standard console output, to a file, or to a network connection.
String name = "Lokesh";
Integer age = 40;

//1 - Using Formatter.format()
String formattedString_1 = new Formatter().format("My name is %s and I am %d years old.\n", name, age).toString();

//2 - Using String.format()
String formattedString_2 = String.format("My name is %s and I am %d years old.\n", name, age);

System.out.print(formattedString_1);
System.out.print(formattedString_2);

//3 - Using System.out.printf()
System.out.printf("My name is %s and I am %d years old.\n", name, age);

The above program produces the same output 3 times.

My name is Lokesh and I am 40 years old.
My name is Lokesh and I am 40 years old.
My name is Lokesh and I am 40 years old.

Also, note that format() is not thread-safe, so necessary precautions must be taken.

2. Conversion Characters

In the previous example, the %s and %d are the conversion characters that are replaced by the formatter engine in runtime. There are many more such patterns corresponding to primitives and different types such as date and time classes.

2.1. Benefits

These specialized conversion characters accomplish three things:

  • They add a level of type safety. For example, by specifying %d, we ensure that only an integer type is formatted at that location; else we get a runtime IllegalFormatConversionException. Similarly, other syntax errors will throw specific subtypes of IllegalFormatException.
  • The text formatting is locale-sensitive and capable of displaying numbers, percentages, dates, and times in many different languages just by specifying a Locale as an argument.
  • Additional flags can be used to further customize the layout. For example, with floating-point numbers, we can specify a precision in the format string.

2.2. Syntax

The general layout of the embedded format string is as follows:

%[argument_index$][flags][width][.precision]conversion_type
  • In the above expression, arguments in brackets [] are optional.
  • The argument_index can be used to reorder or reuse individual arguments from the variable-length argument list by referring to them by number. The first argument is referenced by ” 1$”, the second by ” 2$”, etc.
  • The flags field provides one or more special flag characters controlling the format.
  • The width and precision fields control the size of the output for text and floating-point numbers.
  • The conversion-character is required and determines how the argument is formatted.

The most commonly used conversion types are:

  • %s formats strings.
  • %d formats decimal integers.
  • %f formats floating-point numbers.
  • %b formats booleans.
  • %c formats characters.
  • %t formats date/time values.
  • %n results in the platform-specific line separator.

Similarly, there are more types specific to the date and time-specific conversions. You can read the whole list in its Java doc.

The conversion character can be in UPPERCASE or lowercase, both give the same behavior, except that the result is converted to upper case according to the rules of the applied Locale.

If the argument index does not correspond to an available argument, then a MissingFormatArgumentException is thrown. If an argument is null, then the result is "null" string.

System.out.format("The value is %s", null); //Prints 'The value is null'

3. Formatting Examples

Let us go through simple examples to understand different ways to format text.

3.1. Inserting New Line Separator

Insert %n conversion pattern to insert a new line separator as returned by System.lineSeparator() in the formatted output.

System.out.format("Line 1%nLine 2%nLine 3");

This program outputs:

Line 1
Line 2
Line 3

3.2. Using Argument Index

Use Index$ between the mandatory % symbol and conversion string to refer to an argument. We can refer to an argument multiple times in the same string. Also, we can refer to arguments in any order we want.

In the following example, we are referring to the first argument 2 times in the string.

System.out.printf("The product of %1$d and %1$d is : %2$d", 2, 4); //Prints 'The product of 2 and 2 is : 4'

3.3. Formatting Strings

Apart from using %s for normal string formats, we can use %S for formatting string in UPPERCASE.

System.out.printf("The blog name is : %s", "howtodoinjava");    //Prints 'The blog name is : howtodoinjava'
System.out.printf("The blog name is : %S", "howtodoinjava");    //Prints 'The blog name is : HOWTODOINJAVA'

String formatting can also be used for padded strings. Use a positive number for right-padded string; and a negative number for left-padded string.

System.out.printf("'%15s' %n", "howtodoinjava");    //Prints '  howtodoinjava' 
System.out.printf("'%-15s' %n", "howtodoinjava");   //Prints 'howtodoinjava  '

To limit the formatted string to a max length substring, use the X.Y pattern where X is the padding and Y is the number of chars. In following example, we are first creating a substring of length 3 and then left padding it to 15 characters.

System.out.printf("'%15.3s' %n", "howtodoinjava");    //Prints '            how'

To display the percent sign in the formatted string, use %%. Here percent sign is escaped using a percent sign.

System.out.printf("The interest rate is %d%%", 15);    //Prints 'The interest rate is 15%'

3.4. Formatting Numbers

The %d pattern accepts all the integer types such as byte, short, int, long, and BigInteger.

System.out.printf("The int value is %d %n", 10);    //Prints 'The int value is 10'
System.out.printf("The long value is %d %n", 10L);  //Prints 'The long value is 10 '
System.out.printf("The BigInteger value is %d %n", BigInteger.TEN); //Prints 'The BigInteger value is 10'

Use %f to format float and double values with decimal points.

System.out.printf("The float value is %f %n", 10.0f);   //Prints 'The float value is 10.000000'

Use %.Pf pattern for adding floating-point precision in the formatted string.

System.out.printf("The float value is %.2f %n", 10.0f);   //Prints 'The float value is 10.00'

For locale-based formatting, pass the Locale as the first argument in the method. Also, use comma syntax %,d to insert commas in the numbers based on locale.

System.out.printf(Locale.US, "The amount in US is %,d %n", 1000000);    //Formats to '1,000,000'
System.out.printf(Locale.ITALY, "The amount in UK is %,d %n", 1000000); //Formats to '1.000.000'

3.5. Formatting Date and Time

The date and time conversion patterns start with t or T characters, followed by more specific patterns to show specific date-time information. For more controlled formatting for new Java 8 classes (LocalDate, LocalTime etc.), prefer using DateTimeFormatter class.

For formatting dates, use the following characters:

  • A: full day of the week.
  • d: two-digit day of the month.
  • B: full month name.
  • m: a two-digit month.
  • Y: year in four digits.
  • y: last two digits of the year.

In the following example, we are reusing the argument index to use the same Date instance multiple times in the formatted string. We are using tA, tB and tY to format the date.

Date today = new Date();
System.out.printf("%1$tA, %1$tB %1$tY %n", today); //Prints 'Tuesday, September 2022'

Similarily, for formatting time parts use the following characters:

  • H: hours
  • M: minutes
  • S: seconds
  • L: time in milliseconds
  • N: time in nanoseconds
  • p: AM or PM
  • z: timezone

The following example prints the time in H:N:S pattern. The second line reuses the parameter to format all supplied patterns.

System.out.printf("%1$tH:%1$tM:%1$tS %n", today); //Prints '22:37:15'

There are a few conversion characters for formatting common date/time compositions.

  • R: Time formatted for the 24-hour clock as “%tH:%tM”.
  • T: Time formatted for the 24-hour clock as “%tH:%tM:%tS”.
  • D: Date formatted as “%tm/%td/%ty”.
  • F: ISO 8601 complete date formatted as “%tY-%tm-%td”.
  • c: Date and time formatted as “%ta %tb %td %tT %tZ %tY”.
System.out.printf("%tT %n", today); //Prints '22:37:15'
System.out.printf("%tF %n", today); //Prints '2022-09-13'
System.out.printf("%tc %n", today); //Prints 'Tue Sep 13 22:43:17 IST 2022'

4. Conclusion

This Java tutorial taught us to print formatted output in Java using the format() and printf() methods. We learned to format simple and complex patterns including strings, numbers, dates, primitives and booleans.

We also learned to reuse a method argument in multiple patterns in the same string, and custom patterns to display formatted inbuild date-time patterns. Reiterating again, use the new DateTimeFormatter for formatting date and time classes introduced in Java 8.

Happy Learning !!

Sourcecode on Github

Leave a Reply

0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.