В предыдущих уроках для вывода информации на консоль мы использовали методы print() и println(), которые выводили строки или числа без какого-либо форматирования. Элементарное форматирование мы могли реализовать при помощи добавления к строкам дополнительных пробелов или других символов. В этом уроке мы познакомимся с методами, которые откроют нам новые возможности для форматирования строк в Java.
Краткое содержание урока:
- Использование printf для форматирования в Java
- Форматирование целых чисел
- Форматирование чисел с плавающей точкой
- Форматирование строк
- Локализация
- Использование String.format
Для начала немного мотивации. Рассмотрим пример, в котором рассчитывается и выводится на консоль таблица умножения:
1 2 3 4 5 6 7 8 9 10 |
int[][] multiplyTab = new int[10][10]; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { multiplyTab[i][j] = (i+1)*(j+1); //вывод ряда чисел разделенных знаком табуляции System.out.print(multiplyTab[i][j] + "\t"); } System.out.println(); } |
В данном случае для разделения чисел мы использовали знак табуляции, это дало следующий результат:
Таблица выглядит ровно, но она слишком широкая. Для того, чтобы сделать таблицу более компактной, будем использовать метод printf(). Заменим в предыдущем коде строку
1 |
System.out.print(multiplyTab[i][j] + "\t"); |
на строку
1 |
System.out.printf("%4d", multiplyTab[i][j]); |
Как мы видим, таблица стала компактнее. Более того, теперь мы можем уменьшать или увеличивать промежутки между числами по нашему желанию. Для этого нужно лишь заменить число 4
в выражении «%4d».
Далее рассмотрим метод printf() и его возможности подробнее.
Использование printf для форматирования в Java
Метод printf() принадлежит классу PrintStream, который отвечает за вывод информации. Уже знакомые нам методы print() и println() также являются методами класса PrintStream.
Метод printf определен следующим образом:
1 |
printf(String format, Object... args) |
Первый аргумент format это строка, определяющая шаблон, согласно которому будет происходить форматирование. Для ее записи существуют определенные правила.
В предыдущем примере формат был «%4d», где d означает вывод десятичного целого числа, а 4 — означает то, что если количество знаков в числе меньше, чем 4, то оно будет спереди дополнено пробелами на недостающее (до 4-х) количество знаков (тем самым подвинуто вправо).
Для наглядности приведем еще один пример, который выводит столбиком несколько чисел.
1 |
System.out.printf("%6d%n%6d%n%6d%n%6d%n%6d%n%6d", 666666, 55555, 4444, 333, 22, 1); |
На консоль будет выведено:
1 2 3 4 5 6 |
666666 55555 4444 333 22 1 |
Здесь в строке форматирования мы использовали несколько раз %6d%n, где каждое %6d задает формат для одного из чисел, указанных далее в качестве аргументов. Первое %6d форматирует число 666666, второе %6d форматирует 55555 и т.д. %n означает перевод строки. Поскольку ко всем числам было применено форматирование %6d, то числа, которые содержат менее 6 знаков подвинуты вправо на недостающее количество знаков и тем самым красиво выровнены.
Данный пример иллюстрирует также то, что метод printf может содержать несколько аргументов после строки с форматом. На что указывает Object… args в сигнатуре метода. Эти аргументы должны соответствовать ссылкам на них в строке формата. Например, если в строке формата стоит символ d, отвечающий за вывод целого десятичного числа, а далее в аргументе вы укажете строку, при компиляции произойдет ошибка преобразования формата java.util.IllegalFormatConversionException. Если аргументов больше, чем определено в формате, то лишние аргументы будут игнорироваться.
Общий вид инструкции форматирования следующий:
1 |
%[argument_index$][flags][width][.precision]conversion |
- % — специальный символ, обозначающий начало инструкций форматирования.
- [argument_index$] — целое десятичное число, указывающее позицию аргумента в списке аргументов. Ссылка на первый аргумент
"1$"
, ссылка на второй аргумент"2$"
и т.д. Не является обязательной частью инструкции. Если позиция не задана, то аргументы должны находиться в том же порядке, что и ссылки на них в строке форматирования. - [flags] — специальные символы для форматирования. Например, флаг
"+"
означает, что числовое значение должно включать знак +, флаг"-"
означает выравнивание результата по левому краю, флаг «,» устанавливает разделитель тысяч у целых чисел. Не является обязательной частью инструкции. - [width] — положительное целое десятичное число, которое определяет минимальное количество символов, которые будут выведены. Не является обязательной частью инструкции.
- [.precision] — не отрицательное целое десятичное число с точкойперед ним. Обычно используется для ограничения количества символов. Специфика поведения зависит от вида преобразования. Не является обязательной частью инструкции.
- conversion — это символ, указывающий, как аргумент должен быть отформатирован. Например d для целых чисел, s для строк, f для чисел с плавающей точкой. Является обязательной частью инструкции.
Все возможные флаги и преобразования (conversion) указаны в официальной документации. Здесь мы не ставим цель изучить их все, наша цель — научиться применять форматирование. Поэтому рассмотрим несколько примеров.
Пример 1. Наглядный пример инструкции форматирования в ее полном виде приведен на следующей картинке:
Если мы применим формат с картинки к числу Pi
1 |
System.out.printf("%1$+020.10f", Math.PI); |
Получим следующий результат на консоли:
1 |
+00000003,1415926536 |
Разберем данную инструкцию с конца:
- f — указывает на то, что выводим число с плавающей точкой.
- .10 — выведенное число будет содержать 10 знаков после запятой.
- 20 — всего выведенное число будет иметь ширину в 20 символов
- +0 — недостающие (до 20-ти) символы будут заполнены нулями, перед числом будет указан знак (+)
- 1$ — данный формат применяется к первому аргументу, который находится после строки форматирования. В данном примере это было указывать не обязательно.
Пример 2. Рассмотрим пример демонстрирующий вывод на консоль до знакомства с форматированием и после.
Без форматирования
1 2 3 4 |
Integer i=675; double root; root = Math.sqrt(i); System.out.println("Корень числа " + i + " равен " + root ); |
На консоль будет выведено:
1 |
Корень числа 675 равен 25.98076211353316 |
В этом случае преобразование кода в строку автоматически генерируется компилятором Java. Этот способ плох тем, что при большом количестве переменных и текста для вывода, легко потерять контроль над результатами.
С форматированием
1 2 3 4 |
Integer i=675; double root; root = Math.sqrt(i); System.out.printf("Корень числа %d равен %f", i, root ); |
Где %d отвечает за вывод значения переменной i, а %f за вывод значения переменной root. При этом мы уже не используем конкатенацию.
На консоль будет выведено:
1 |
Корень числа 675 равен 25,980762 |
Как мы видим, формат автоматически округляет число до 6 знаков после запятой. Однако, при форматировании мы можем устанавливать такое количество знаков после запятой, которое нам нужно, например:
1 |
System.out.printf("Корень числа %d равен %.2f", i, root ); |
Выведет число с двумя знаками после запятой.
Далее на примерах рассмотрим наиболее популярные правила форматирования.
Форматирование целых чисел
Вывод целого числа
1 |
System.out.printf("%d", 7845); // --> "7845" |
Вывод целого числа с разделением тысяч
1 |
System.out.printf("%,d", 7845); // --> "7 845" |
Число менее 7 знаков будет «подвинуто» вправо на недостающее количество знаков.
1 |
System.out.printf("%7d", 7845); // --> " 7845" |
Число менее 7 знаков будет дополнено нулями слева на недостающее количество знаков.
1 |
System.out.printf("%07d", 7845); // --> "0007845" |
Число будет дополнено знаком + и, если оно менее 7 знаков, то будет дополнено нулями на недостающее количество знаков.
1 |
System.out.printf("%+07d", 7845); //--> "+007845" |
Число будет выровнено по левому краю и, если оно менее 7 знаков, то будет дополнено пробелами справа на недостающее количество знаков.
1 |
System.out.printf("%-7d", 7845); // --> "7845 " |
Разумеется вместо 7 можно использовать любое другое положительное целое число.
Форматирование чисел с плавающей точкой
Вывод числа e. Автоматическое округление до 6 знаков после запятой.
1 |
System.out.printf("%f", Math.E); // --> "2,718282" |
Число менее 10 знаков будет «подвинуто» вправо на недостающее количество знаков.
1 |
System.out.printf("%10f", Math.E); // --> " 2,718282" |
Число менее 10 знаков будет дополнено нулями слева на недостающее количество знаков.
1 |
System.out.printf("%010f", Math.E); // --> "002,718282" |
Число будет дополнено знаком + и, если оно менее 10 знаков, то будет дополнено нулями на недостающее количество знаков.
1 |
System.out.printf("%+010f", Math.E); // --> "+02,718282" |
Число будет выведено с 15 знаками после запятой.
1 |
System.out.printf("%.15f", Math.E); // --> "2,718281828459045" |
Число будет выведено с 3-мя знаками после запятой и, если оно менее 8 символов, то будет «подвинуто» вправо на недостающее количество знаков.
1 |
System.out.printf("%8.3f", Math.E); // --> " 2,718" |
Число будет выровнено по левому краю, выведено с 3-мя знаками после запятой и, если оно менее 8 знаков, то будет дополнено пробелами справа на недостающее количество знаков.
1 |
System.out.printf("%-8.3f", Math.E); // --> "2,718 " |
Форматирование строк
Вывод строки.
1 |
System.out.printf("%s%n", "Hello"); // --> "Hello" |
Если строка содержит менее 10 символов, то «подвинуть » ее вправо на недостающее количество символов.
1 |
System.out.printf("%10s%n", "Hello"); // --> " Hello" |
Строка будет выровнена по левому краю и, если она менее 10 символов, то будет дополнена справа пробелами на недостающее количество символов.
1 |
System.out.printf("%-10s%n", "Hello"); // --> "Hello " |
Выведет первые 3 символа строки.
1 |
System.out.printf("%.3s%n", "Hello"); // --> "Hel" |
Выведет первые 3 символа строки и подвинет их вправо на недостающее до 8 количество символов.
1 |
System.out.printf("%8.3s%n", "Hello"); // --> " Hel" |
Локализация
В разных странах некоторые записи принято производить по-разному. Например, в одних странах дробное число принято писать с точкой «3.68», а в других с запятой «3,68». Java нам позволяет соблюдать эти традиции. Метод printf имеет еще одну сигнатуру:
printf(Locale l, String format, Object… args)
Первым аргументом стоит Locale l, который и определяет локализацию. Для того, чтобы использовать локализацию необходимо вначале файла с вашим кодом импортировать библиотеку java.util.Locale.
1 |
import java.util.Locale; |
Рассмотрим несколько примеров применения:
1 2 3 |
System.out.printf(Locale.ENGLISH,"%,d%n", 1000000 );// 1,000,000 System.out.printf(Locale.GERMAN,"%,d%n", 1000000 ); // 1.000.000 System.out.printf(Locale.FRANCE,"%,d%n", 1000000 ); // 1 000 000 |
В зависимости от указанной страны используются разные разделители для тысяч.
1 2 |
System.out.printf(Locale.ENGLISH,"%.2f%n", 9.87 ); //9.87 System.out.printf(Locale.FRANCE,"%.2f%n", 9.87 ); //9,87 |
В зависимости от указанной страны используются разные разделители у дробных чисел.
Использование String.format
В случае, если нет необходимости выводить отформатированную строку, а нужно просто ее сохранить для дальнейшего использования (например, для записи в лог или базу данных) следует использовать метод format из класса String. Принципы форматирования в этом случае абсолютно такие же, как у описанного выше printf, но этот метод вместо вывода строки сохраняет ее как отформатированную строку.
Пример использования:
1 |
String s = String.format("Курс валют: %-4s%-8.4f %-4s%-8.4f","USD", 58.4643, "EUR", 63.3695); |
Это далеко не все возможности форматирования в Java. Существуют несколько классов, предназначенных для более сложного форматирования, но их оставим для дальнейших уроков.
Закончить урок хочется примером, в котором используются форматирование всех изученных в этом уроке типов данных: целых чисел, чисел с плавающей точкой и строк.
Пример: Таблица курсов валют
1 2 3 4 5 6 7 8 9 |
System.out.printf("%-5s%-11s%-25s%-11s%n","Код","За единиц","Валюты","Рублей РФ"); System.out.println("-----------------------------------------------------"); System.out.printf("%-5s%-11d%-25s%-11.4f%n","AUD",1,"Австралийский доллар",44.9883); System.out.printf("%-5s%-11d%-25s%-11.4f%n","GBP",1,"Фунт стерлингов",86.8429); System.out.printf("%-5s%-11d%-25s%-11.4f%n","BYR",10000,"Белорусский рубль",39.7716); System.out.printf("%-5s%-11d%-25s%-11.4f%n","DKK",10,"Датская крона",84.9192); System.out.printf("%-5s%-11d%-25s%-11.4f%n","USD",1,"Доллар США",58.4643); System.out.printf("%-5s%-11d%-25s%-11.4f%n","EUR",1,"Евро",63.3695); System.out.printf("%-5s%-11d%-25s%-11.4f%n","KZT",100,"Казахский тенге",31.4654); |
Результат вывода на консоль:
1 2 3 4 5 6 7 8 9 |
Код За единиц Валюты Рублей РФ ----------------------------------------------------- AUD 1 Австралийский доллар 44,9883 GBP 1 Фунт стерлингов 86,8429 BYR 10000 Белорусский рубль 39,7716 DKK 10 Датская крона 84,9192 USD 1 Доллар США 58,4643 EUR 1 Евро 63,3695 KZT 100 Казахский тенге 31,4654 |
Полезные ссылки из официальной документации: