Я использую стандартный ConsoleHandler
от java.util.logging
, и по умолчанию вывод консоли направлен на поток ошибок (т.е. System.err
).
Как изменить вывод консоли в выходной поток (т.е. System.out
)?
Я использую стандартный ConsoleHandler
от java.util.logging
, и по умолчанию вывод консоли направлен на поток ошибок (т.е. System.err
).
Как изменить вывод консоли в выходной поток (т.е. System.out
)?
Я прибыл в
SimpleFormatter fmt = new SimpleFormatter();
StreamHandler sh = new StreamHandler(System.out, fmt);
logger.addHandler(sh);
Handler consoleHandler = new Handler(){
@Override
public void publish(LogRecord record)
{
if (getFormatter() == null)
{
setFormatter(new SimpleFormatter());
}
try {
String message = getFormatter().format(record);
if (record.getLevel().intValue() >= Level.WARNING.intValue())
{
System.err.write(message.getBytes());
}
else
{
System.out.write(message.getBytes());
}
} catch (Exception exception) {
reportError(null, exception, ErrorManager.FORMAT_FAILURE);
}
}
@Override
public void close() throws SecurityException {}
@Override
public void flush(){}
};
Я понял один путь. Сначала удалите обработчик консоли по умолчанию:
setUseParentHandlers (ложь);
Затем подкласс ConsoleHandler и в конструкторе:
setOutputStream (System.out);
Хм, я несколько раз немного подтолкнул ногу, пытаясь выполнить этот подвиг. До того, как я отправился сюда, мне удалось вызвать следующий хак. Ужасно, но, похоже, это делается.
public class StdoutConsoleHandler extends ConsoleHandler {
protected void setOutputStream(OutputStream out) throws SecurityException {
super.setOutputStream(System.out); // kitten killed here :-(
}
}
Остерегайтесь: вызов setOutputStream() из конструктора заманчиво, но он (как уже указывал Джон Скит) закрыл System.err. Безумные навыки!
Взгляните на документы и источник для ConsoleHandler - я уверен, что вы можете легко написать версию, которая просто использует System.r вместо System.out. (Позор, который ConsoleHandler не позволяет настроить, если честно.)
Тогда это просто случай настройки системы ведения журнала, чтобы использовать ваш новый StdoutHandler (или как вы его называете) обычным способом.
Если еще есть кто-то, ищущий решение этой проблемы. Вот что я придумал, наконец: я просто подклассифицировал StreamHandler и добавил дополнительный параметр MaxLevel, который проверяется в начале publish(). Если уровень события регистрации больше MaxLevel, публикация не будет выполняться дальше. Вот подробности:
MaxlevelStreamHandler.java Основной класс ниже.
package helper;
/**
* The only difference to the standard StreamHandler is
* that a MAXLEVEL can be defined (which then is not published)
*
* @author Kai Goergen
*/
import java.io.PrintStream;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
public class MaxlevelStreamHandler extends StreamHandler {
private Level maxlevel = Level.SEVERE; // by default, put out everything
/**
* The only method we really change to check whether the message
* is smaller than maxlevel.
* We also flush here to make sure that the message is shown immediately.
*/
@Override
public synchronized void publish(LogRecord record) {
if (record.getLevel().intValue() > this.maxlevel.intValue()) {
// do nothing if the level is above maxlevel
} else {
// if we arrived here, do what we always do
super.publish(record);
super.flush();
}
}
/**
* getter for maxlevel
* @return
*/
public Level getMaxlevel() {
return maxlevel;
}
/**
* Setter for maxlevel.
* If a logging event is larger than this level, it won't be displayed
* @param maxlevel
*/
public void setMaxlevel(Level maxlevel) {
this.maxlevel = maxlevel;
}
/** Constructor forwarding */
public MaxlevelStreamHandler(PrintStream out, Formatter formatter) {
super(out, formatter);
}
/** Constructor forwarding */
public MaxlevelStreamHandler() {
super();
}
}
Основной класс
Чтобы показать некоторые события в stdout и некоторые из stderr, просто настройте два StreamLoggers, один для критических событий и один для всех остальных, и отключите стандартный консольный логгер:
// setup all logs that are smaller than WARNINGS to stdout
MaxlevelStreamHandler outSh = new MaxlevelStreamHandler(System.out, formatter);
outSh.setLevel(Level.ALL);
outSh.setMaxlevel(Level.INFO);
logger.addHandler(outSh);
// setup all warnings to stdout & warnings and higher to stderr
StreamHandler errSh = new StreamHandler(System.err, formatter);
errSh.setLevel(Level.WARNING);
logger.addHandler(errSh);
// remove default console logger
logger.setUseParentHandlers(false);
logger.info("info");
logger.warning("warning");
logger.severe("severe");
Надеюсь, это поможет!
Обновление: я добавил super.flush() сразу после super.publish(), чтобы убедиться, что сообщение отображается немедленно. Раньше у меня были проблемы с тем, что сообщения журнала всегда показывались в конце. Теперь это часть кода выше.
У меня была аналогичная проблема. Я хотел зарегистрировать INFO и ниже до System.out
, а ПРЕДУПРЕЖДЕНИЕ и выше - System.err
. Вот решение, которое я реализовал:
public class DualConsoleHandler extends StreamHandler {
private final ConsoleHandler stderrHandler = new ConsoleHandler();
public DualConsoleHandler() {
super(System.out, new SimpleFormatter());
}
@Override
public void publish(LogRecord record) {
if (record.getLevel().intValue() <= Level.INFO.intValue()) {
super.publish(record);
super.flush();
} else {
stderrHandler.publish(record);
stderrHandler.flush();
}
}
}
Конечно, вы могли бы сделать его более гибким, например, закодировав жестко привязанную ссылку на Level.INFO
. Но это сработало для меня, чтобы получить базовый двухпоточный журнал. (Кстати, советы о том, что не подклассы ConsoleHandler, чтобы избежать закрытия System.err
, были очень полезны.)
Если вы используете ведение журнала Java, вы можете изменить обработчик по умолчанию:
Например, для файлов: Обработчик fh = новый FileHandler (FILENAME); Logger.getLogger(LOGGER_NAME).addHandler(ФХ);
Если вы хотите вывести на поток, вы можете использовать StreamHandler, я думаю, вы можете настроить его с любым потоком, который вам нужен, включая системный поток.
В процессе построения ConsoleHandler захватит снимок System.err
. Один из вариантов - обмен глобальным потоком ошибок с глобальным потоком out, а затем создание ConsoleHandler.
final PrintStream err = System.err;
System.setErr(System.out);
ConsoleHandler h = new ConsoleHandler(); //Snapshot of System.err
System.setErr(err);
Это предполагает, что код имеет разрешение на изменение потока ошибок и что ни один другой исполняемый код не обращается к потоку ошибок. Короче говоря, это вариант, но есть более безопасные альтернативы.
Когда мы создаем новый объект ConsoleHandler, выходной поток по умолчанию - "system.err". К сожалению, Java не предоставляет публичный метод для класса ConsoleHandler для установки выходного потока. Поэтому он может быть установлен только во время создания объекта. Поскольку класс ConsoleHandler расширяет StreamHandler, у которого есть защищенный метод "setOutputStream", чтобы явно задать выходной поток. Чтобы установить выходной поток для ConsoleHandler, просто переопределите этот метод во время нового вызова для создания объекта.
ConsoleHandler consoleHandler = new ConsoleHandler (){
@Override
protected synchronized void setOutputStream(OutputStream out) throws SecurityException {
super.setOutputStream(System.out);
}
};
Если вы установите setUseParentHandlers (false); только класс THAT установлен. Другие классы в приложении все равно передадут его через stderr.
Просто добавьте StreamHandler и в вызове конструктора Super (System.out,). Это позволит избежать закрытия System.err - Спасибо