Подтвердить что ты не робот

Как изменить вывод консоли управления java из std err в std?

Я использую стандартный ConsoleHandler от java.util.logging, и по умолчанию вывод консоли направлен на поток ошибок (т.е. System.err).

Как изменить вывод консоли в выходной поток (т.е. System.out)?

4b9b3361

Ответ 1

Я прибыл в

 SimpleFormatter fmt = new SimpleFormatter();
 StreamHandler sh = new StreamHandler(System.out, fmt);
 logger.addHandler(sh);

Ответ 2

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(){}
        };

Ответ 3

Я понял один путь. Сначала удалите обработчик консоли по умолчанию:

setUseParentHandlers (ложь);

Затем подкласс ConsoleHandler и в конструкторе:

setOutputStream (System.out);

Ответ 4

Хм, я несколько раз немного подтолкнул ногу, пытаясь выполнить этот подвиг. До того, как я отправился сюда, мне удалось вызвать следующий хак. Ужасно, но, похоже, это делается.

public class StdoutConsoleHandler extends ConsoleHandler {
  protected void setOutputStream(OutputStream out) throws SecurityException {
    super.setOutputStream(System.out); // kitten killed here :-(
  }
}

Остерегайтесь: вызов setOutputStream() из конструктора заманчиво, но он (как уже указывал Джон Скит) закрыл System.err. Безумные навыки!

Ответ 5

Взгляните на документы и источник для ConsoleHandler - я уверен, что вы можете легко написать версию, которая просто использует System.r вместо System.out. (Позор, который ConsoleHandler не позволяет настроить, если честно.)

Тогда это просто случай настройки системы ведения журнала, чтобы использовать ваш новый StdoutHandler (или как вы его называете) обычным способом.

Ответ 6

Если еще есть кто-то, ищущий решение этой проблемы. Вот что я придумал, наконец: я просто подклассифицировал 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(), чтобы убедиться, что сообщение отображается немедленно. Раньше у меня были проблемы с тем, что сообщения журнала всегда показывались в конце. Теперь это часть кода выше.

Ответ 7

У меня была аналогичная проблема. Я хотел зарегистрировать 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, были очень полезны.)

Ответ 8

Если вы используете ведение журнала Java, вы можете изменить обработчик по умолчанию:

Например, для файлов:   Обработчик fh = новый FileHandler (FILENAME);   Logger.getLogger(LOGGER_NAME).addHandler(ФХ);

Если вы хотите вывести на поток, вы можете использовать StreamHandler, я думаю, вы можете настроить его с любым потоком, который вам нужен, включая системный поток.

Ответ 9

В процессе построения 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);

Это предполагает, что код имеет разрешение на изменение потока ошибок и что ни один другой исполняемый код не обращается к потоку ошибок. Короче говоря, это вариант, но есть более безопасные альтернативы.

Ответ 10

Когда мы создаем новый объект 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);
            }
        };

Ответ 11

Если вы установите setUseParentHandlers (false); только класс THAT установлен. Другие классы в приложении все равно передадут его через stderr.

Ответ 12

Просто добавьте StreamHandler и в вызове конструктора Super (System.out,). Это позволит избежать закрытия System.err - Спасибо