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

System.out закрыт? Могу ли я снова открыть его?

Я помогал другу написать код Java, который мало знает о Java. Поэтому я написал ему некоторые вспомогательные функции, чтобы легко сделать все, что было немного необычно в его глазах. Одна из них - это функция, которая записывает строку в OutputStream. Посмотрите:

public void write(String txt, OutputStream out) {
    PrintWriter printer = new PrintWriter(out);
    printer.print(txt);
    printer.close();
}

Теперь вы можете использовать это легко по-разному, чтобы писать везде, где хотите. Например, вы можете сделать это:

(new StreamHelper()).write("Hello Test", System.out);

Сделав это, я узнал, что впоследствии System.out.println() больше ничего не пишет в оболочку. Поэтому я думаю, что, возможно, printer.close() автоматически также закрывается System.out, и мне интересно, как его активировать, чтобы я мог использовать его после завершения этой функции.

Является ли мое предположение правильным? (Как я мог узнать, не спрашивая здесь?)

Как я могу продолжать использовать System.out после вызова функции write()?

Есть ли лучшие способы написать такую ​​вспомогательную функцию?

4b9b3361

Ответ 1

Общий контракт для OutputStream close:

public void close()            throws IOException Закрывает этот выходной поток и освобождает любые системные ресурсы, связанные с этим потоком. Общий контракт close заключается в том, что он закрывает выходной поток. Закрытый поток не может выполнять выходные операции и не может быть повторно открыт.

PrintStream 's

public void close() Закрыть поток. Это делается путем промывки поток, а затем закрытие основного потока вывода.

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

Даже если в вашем случае может показаться разумным закрыть поток обертки, факт в том, что вы не должны, потому что вы закрываете поток, открытый где-то еще.

Короче:

public void write(String txt, OutputStream out) {
    PrintWriter printer = new PrintWriter(out);
    printer.print(txt);
    printer.flush();
    //it is very unpolite to close someone else streams!
    //printer.close();
}

О, и, кстати, вы можете изменить имя функции на print, а не на write.

Ответ 2

Как и другие, поток должен быть закрыт там, где он был открыт. Однако вы можете написать фасад, чтобы защитить поток от закрывания:

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class UnclosableOutputStream extends FilterOutputStream {

    public UnclosableOutputStream(OutputStream out) {
        super(out);
    }

    @Override
    public void close() throws IOException {
        out.flush();
    }
}

и используйте его следующим образом:

new StreamHelper().write("Hello Test", new UnclosableOutputStream(System.out));

Может оказаться полезным для тестовых сценариев и т.д.

Ответ 3

System.out - это PrintStream, поэтому код, который вы предоставили выше, не имеет никакого преимущества перед тем, как просто позвонить System.out.print напрямую. Причина, по которой он больше не пишет, заключается в том, что close действительно закрыл System.out.

Если это для ведения журнала, узнайте log4j для своего друга или помогите ему узнать его. Log4j обрабатывает ситуации, когда вам достаточно хорошо писать в поток файлов, стандартную и т.д. Одновременно.

Ответ 4

Вы можете проверить, прошел ли вход out System.out и выборочно решить не закрывать.

Требуется вызов flush(). Обратите внимание, что я выполняю проверку ==, так как ссылки будут идентичными, если вы должны были вызвать этот метод write с аргументом System.out.

public void write(String txt, OutputStream out) {
    PrintWriter printer = new PrintWriter(out);
    printer.print(txt);
    printer.flush();

    if(out != System.out) {
        printer.close();
    }
}

Но, честно говоря, я бы придерживался другого метода закрытия или вызова этого метода writeAndClose, чтобы избежать путаницы.

Если вы хотите сохранить абстракцию (как намечено @Urs), сделайте следующее. Но я не вижу смысла в этом довольно сложном

public void write(String txt, OutputStream out) {
    PrintWriter printer = new PrintWriter(out);
    printer.print(txt);
    printer.flush();
}

public void close(OutputStream out) {
    out.close();
}

Ответ 5

Посмотрите на это с точки зрения вызывающего абонента.

Вызывающий имеет OutputStream своего рода, и вызывает метод с именем write(). После завершения вызова вызывающий абонент обнаруживает, что поток был закрыт.

На мой взгляд, ваш метод write() просто не должен вызывать printer.close(). Последний закрывает поток, предоставляемый вызывающим абонентом, и, вероятно, не тот, который ожидает абонент.

Если вам нужно очистить поток, вы можете использовать flush().

Ответ 6

Сделайте то, что предлагает Стас Курилин.

В общем, потоки должны быть закрыты стороной, открывшей/создавшей их.

В вашем методе просто промойте поток. Закройте его везде, где он был открыт, когда он больше не нужен.