Тема 26. Работа с консолью и логами - BelyiZ/JavaCourses GitHub Wiki
Материал находится на стадии "Черновик"
Содержание:
Наиболее простой способ взаимодействия с пользователем представляет консоль: можем выводить на консоль некоторую информацию или, наоборот, считывать с консоли некоторые данные. Для взаимодействия с консолью в Java применяется класс System, а его функциональность собственно обеспечивает консольный ввод и вывод.
Ввод и вывод на консоль
Вывод на консоль
Для создания потока вывода в класс System
определен объект out
.
В этом объекте определен метод println
, который позволяет вывести на консоль некоторое значение с последующим переводом курсора консоли на следующую строку.
Например:
public class Program {
public static void main(String[] args) {
System.out.println("Hello world!");
System.out.println("Bye world...");
}
}
В метод println
передается любое значение, как правило, строка, которое надо вывести на консоль.
И в данном случае мы получим следующий вывод:
Hello world!
Bye world...
При необходимости можно и не переводить курсор на следующую строку. В этом случае можно использовать метод System.out.print(), который аналогичен println за тем исключением, что не осуществляет перевода на следующую строку.
public class Program {
public static void main(String[] args) {
System.out.print("Hello world!");
System.out.print("Bye world...");
}
}
Консольный вывод данной программы:
Hello world!Bye world...
Но с помощью метода System.out.print
также можно осуществить перевод каретки на следующую строку.
Для этого надо использовать escape-последовательность \n:
System.out.print("Hello world \n");
Нередко необходимо подставлять в строку какие-нибудь данные. Например, у нас есть два числа, и мы хотим вывести их значения на экран. В этом случае мы можем, например, написать так:
public class Program {
public static void main(String[] args) {
int x=5;
int y=6;
System.out.println("x=" + x + "; y=" + y);
}
}
Консольный вывод программы:
x=5; y=6
Но в Java есть также функция для форматированного вывода, унаследованная от языка С: System.out.printf()
.
С ее помощью мы можем переписать предыдущий пример следующим образом:
int x=5;
int y=6;
System.out.printf("x=%d; y=%d \n", x, y);
В данном случае символы %d обозначают спецификатор, вместо которого подставляет один из аргументов. Спецификаторов и соответствующих им аргументов может быть множество. В данном случае у нас только два аргумента, поэтому вместо первого %d подставляет значение переменной x, а вместо второго - значение переменной y. Сама буква d означает, что данный спецификатор будет использоваться для вывода целочисленных значений.
Кроме спецификатора %d мы можем использовать еще ряд спецификаторов для других типов данных:
-
%x: для вывода шестнадцатеричных чисел
-
%f: для вывода чисел с плавающей точкой
-
%e: для вывода чисел в экспоненциальной форме, например, 1.3e+01
-
%c: для вывода одиночного символа
-
%s: для вывода строковых значений
Например:
public class Program {
public static void main(String[] args) {
String name = "Tom";
int age = 30;
float height = 1.7f;
System.out.printf("Name: %s Age: %d Height: %.2f \n", name, age, height);
}
}
При выводе чисел с плавающей точкой мы можем указать количество знаков после запятой, для этого используем спецификатор на %.2f, где .2 указывает, что после запятой будет два знака.
В итоге мы получим следующий вывод:
Name: Tom Age: 30 Height: 1,70
Ввод с консоли Для получения ввода с консоли в классе System определен объект in. Однако непосредственно через объект System.in не очень удобно работать, поэтому, как правило, используют класс Scanner, который, в свою очередь использует System.in. Например, напишем маленькую программу, которая осуществляет ввод чисел:
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Input a number: ");
int num = in.nextInt();
System.out.printf("Your number: %d \n", num);
in.close();
}
}
Так как класс Scanner
находится в пакете java.util
, то мы вначале его импортируем с помощью инструкции import java.util.Scanner
.
Для создания самого объекта Scanner в его конструктор передается объект System.in
.
После этого мы можем получать вводимые значения.
Например, в данном случае вначале выводим приглашение к вводу и затем получаем вводимое число в переменную num.
Чтобы получить введенное число, используется метод in.nextInt()
;, который возвращает введенное с клавиатуры целочисленное значение.
Пример работы программы:
Input a number: 5
Your number: 5
Класс Scanner
имеет еще ряд методов, которые позволяют получить введенные пользователем значения:
-
next(): считывает введенную строку до первого пробела
-
nextLine(): считывает всю введенную строку
-
nextInt(): считывает введенное число int
-
nextDouble(): считывает введенное число double
-
nextBoolean(): считывает значение boolean
-
nextByte(): считывает введенное число byte
-
nextFloat(): считывает введенное число float
-
nextShort(): считывает введенное число short
То есть для ввода значений каждого примитивного типа в классе Scanner
определен свой метод.
Например, создадим программу для ввода информации о человеке:
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Input name: ");
String name = in.nextLine();
System.out.print("Input age: ");
int age = in.nextInt();
System.out.print("Input height: ");
float height = in.nextFloat();
System.out.printf("Name: %s Age: %d Height: %.2f \n", name, age, height);
in.close();
}
}
Здесь последовательно вводятся данные типов String
, int
, float
и потом все введенные данные вместе выводятся на консоль.
Пример работы программы:
Input name: Tom
Input age: 34
Input height: 1,7
Name: Tom Age: 34 Height: 1,70
Обратите внимание, что для ввода значения типа float
(то же самое относится к типу double
) применяется число "1,7", где разделителем является запятая, а не "1.7", где разделителем является точка. В данном случае все зависит от текущей языковой локализации системы. В моем случае русскоязычная локализация, соответственно вводить необходимо числа, где разделителем является запятая.
То же самое касается многих других локализаций, например, немецкой, французской и т.д., где применяется запятая.
Логирование
При создании приложений мы часто сталкиваемся с ошибками, которые необходимо отлаживать.
Итак, с помощью логов мы можем легко получить информацию о том, что происходит в приложении, с записью ошибок и необычных обстоятельств.
Теперь вам может показаться, что почему бы не использовать оператор System.out.print()
в Java
.
Проблема с этими утверждениями состоит в том, что сообщения журнала будут печататься только на консоли. Поэтому, как только вы закроете консоль автоматически, все журналы будут потеряны. Они не хранятся постоянно и будут отображаться один за другим, так как это однопоточная среда.
Чтобы избежать таких проблем, логирование в Java
упрощается с помощью API
, предоставляемого через пакет java.util.logging
пакет org.apache.log4j.*
.
Компоненты Компоненты ведения журнала помогают разработчику создавать их, передавать в соответствующее место назначения и поддерживать надлежащий формат. Ниже приведены три компонента:
Loggers – отвечает за сбор записей журнала и передачу их соответствующему заявителю. Appenders или Handlers – они отвечают за запись событий журнала в пункт назначения. Аппендеры форматируют события с помощью макетов перед отправкой результатов. Layouts или Formatters – отвечает за определение того, как данные выглядят, когда они появляются в записи журнала.
Что такое Логгеры (Logger) в Java? Логгеры (Logger) в Java – это объекты, которые запускают события журнала. Они создаются и вызываются в коде приложения, где генерируют события журнала перед передачей их следующему компоненту, который является Appender.
Вы можете использовать несколько логгеров в одном классе для ответа на различные события или использовать в иерархии. Они обычно называются с использованием иерархического пространства имен, разделенных точками. Кроме того, все имена Logger должны основываться на классе или имени пакета зарегистрированного компонента.
Кроме того, каждый логгер отслеживает ближайшего существующего предка в пространстве имен, а также имеет связанный с ним «уровень».
Как создать? Вы должны использовать Logger.getLogger(). Метод getLogger() идентифицирует имя Logger и принимает строку в качестве параметра. Таким образом, если Logger уже существует, он возвращается, в противном случае создается новый.
Синтаксис
static Logger logger = Logger.getLogger(SampleClass.class.getName());
Здесь SampleClass – это имя класса, для которого мы получаем объект Logger.
Пример:
public class Customer{
private static final Logger LOGGER = Logger.getLogger(Customer.class);
public void getCustomerDetails() {
}
}
Уровни Уровни журналов используются для классификации их по степени серьезности или влиянию на стабильность приложения. Пакет org.apache.log4j.* и java.util.logging предоставляют разные уровни ведения журнала.
Пакет org.apache.log4j.* предоставляет следующие уровни в порядке убывания:
FATAL; ERROR; WARN; INFO; DEBUG.
Пакет java.util.logging предоставляет следующие уровни в порядке убывания:
SEVERE(HIGHEST LEVEL); WARNING; INFO; CONFIG; FINE; FINER; FINEST(LOWEST LEVEL). Помимо этого, вышеприведенный пакет также предоставляет два дополнительных уровня ALL и OFF используются для регистрации всех сообщений и отключения регистрации соответственно.
Пример с использованием пакета org.apache.log4j.*
import org.apache.log4j.Logger;
public class Customer {
static Logger logger = Logger.getLogger(Customer.class);
public static void main(String[] args) {
logger.error("ERROR");
logger.warn("WARNING");
logger.fatal("FATAL");
logger.debug("DEBUG");
logger.info("INFO");
System.out.println("Final Output");
}
}
Таким образом, если в нашем файле log4j.properties ваш вывод является корневым логгером уровня WARN, то все сообщения об ошибках с более высоким приоритетом, чем WARN, будут напечатаны, как показано ниже:
Вы также можете установить уровень с помощью метода setLevel() из пакета java.util.logging , как java.util.logging ниже:
logger.setLevel(Level.WARNING);
Пример с использованием пакета java.util.logging
package edureka;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.*;
class EdurekaLogger {
private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
public void sampleLog(){
LOGGER.log(Level.WARNING, "Welcome to Edureka!");
}
}
public class Customer {
public static void main(String[] args)
{
EdurekaLogger obj = new EdurekaLogger();
obj.sampleLog();
LogManager slg = LogManager.getLogManager();
Logger log = slg.getLogger(Logger.GLOBAL_LOGGER_NAME);
log.log(Level.WARNING, "Hi! Welcome from Edureka");
}
}
Чтобы включить вход в приложение с помощью пакета org.apache.log4j.* Или пакета java.util.logging , необходимо настроить файл свойств. Далее в этой статье о Logger в Java давайте обсудим файл свойств обоих из них.
Файл свойств пакета Log4j и Java Util Пример файла свойств Log4j
# Enable Root logger option
log4j.rootLogger=INFO, file, stdout
# Attach appenders to print file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=E:loglogging.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Attach appenders to print on console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
Файл свойств Log4j создается внутри папки src проекта.
log4j.appender.file = org.apache.log4j.RollingFileAppender -> Печатает все журналы в файле
log4j.appender.stdout = org.apache.log4j.ConsoleAppender -> Печатает все журналы в консоли
log4j.appender.file.File = D: loglogging.log -> Указывает расположение файла журнала
log4j.appender.file.MaxFileSize = 10 МБ -> Максимальный размер файла журнала до 10 МБ
log4j.appender.file.MaxBackupIndex = 5 -> Ограничивает количество файлов резервных копий до 5
log4j.appender.file.layout = org.apache.log4j.PatternLayout -> Указывает шаблон, в котором журналы будут печататься в файл журнала.
log4j.appender.file.layout.ConversionPattern =% d {гггг-ММ-дд ЧЧ: мм: сс}% -5p% c {1}:% L -% m% n -> Устанавливает шаблон преобразования по умолчанию.
Пример файла свойств пакета Java Util
handlers= java.util.logging.ConsoleHandler
.level= WARNING
# Output will be stored in the default directory
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 60000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Level of logs will be limited to WARNING and above.
java.util.logging.ConsoleHandler.level = WARNING
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
Здесь
java.util.logging.FileHandler.pattern =% h / java% u.log -> Файлы журнала будут записаны в C: TEMPjava1.log
java.util.logging.FileHandler.limit = 50000 -> Максимальная сумма, которую регистратор записывает в один файл в байтах.
java.util.logging.FileHandler.count = 1 -> Указывает количество выходных файлов
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter -> Упоминает форматер, используемый для форматирования. Здесь используется XML Formatter.
java.util.logging.ConsoleHandler.level = WARNING -> Устанавливает уровень журнала по умолчанию для WARNING
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -> Указывает форматер, используемый всеми ConsoleHandler. Здесь используется SimpleFormatter.
Регистрация событий
Чтобы регистрировать события в Java, вы должны убедиться, что вы назначаете уровень, чтобы легко отфильтровать события. Чтобы назначить уровень и упомянуть сообщение, вы можете использовать следующие методы:
Способ 1
logger.log(Level.INFO, “Display message”);
Here, level is INFO and the message to be printed is "Display Message".
Способ 2
logger.info(“Display message”);
Чтобы убедиться, что Logger регистрирует только события, которые находятся на уровне или выше уровня INFO, вы можете использовать метод setLevel(), описанный выше.
Appender или Handlers Appender или Handlers отвечают за запись событий журнала в пункт назначения. Каждый регистратор имеет доступ к нескольким обработчикам и получает сообщение журнала от регистратора. Затем Appenders используют средства форматирования или макеты для форматирования событий и отправки их в соответствующее место назначения.
Appender можно отключить с помощью метода setLevel (Level.OFF). Два наиболее стандартных обработчика в пакете java.util.logging :
FileHandler: записать сообщение журнала в файл. ConsoleHandler: записывает сообщение журнала в консоль. Layout или Formatters Используются для форматирования и преобразования данных в журнале событий. Каркасы журналов предоставляют макеты для HTML, XML, Syslog, JSON, простого текста и других журналов.