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

В Java, когда я вызываю OutputStream.close(), мне всегда нужно вызывать OutputStream.flush() раньше?

Если я просто вызываю close() в выходном потоке, выход гарантирован или мне нужно всегда звонить flush()

4b9b3361

Ответ 1

Закрыть() всегда сбрасывается, поэтому нет необходимости звонить.

EDIT: Этот ответ основан на здравом смысле и на всех встречах, с которыми я столкнулся. Кто собирается внедрить close() для буферизованного потока без сброса буфера первым? Нет вреда для вызова flush прямо перед close(). Однако есть последствия, если flush() называется чрезмерно. Он может победить под механизмом буферизации.

Ответ 2

Пока close должен вызывать flush, это немного сложнее, чем это...

Во-первых, декораторы (такие как BufferedOutputStream) являются обычными в Java. Конструкция декоратора может выйти из строя, поэтому вам нужно close "сырой" поток в блоке finally, чей try включает декоратор. В случае исключения вам обычно не требуется close декоратор (за исключением, например, для плохо реализованных декораторов сжатия). Обычно вам нужно flush декоратор в случае исключения. Поэтому:

final RawOutputStream rawOut = new RawOutputStream(rawThing);
try {
    final DecoratedOutputStream out = new DecoratedOutputStream(rawOut);
    // ... stuff with out within ...
    out.flush();
} finally {
    rawOut.close();
}

В начало, методы декоратора close часто выполняются некорректно. До недавнего времени это включало некоторые из java.io.

Конечно, вы, вероятно, захотите использовать Execute Around idiom для хранения DRY (ish).

Ответ 3

Если вы хотите, чтобы поток был сброшен, да, вызовите flush() перед вызовом close().

Несмотря на все другие ответы на обратное (но, как указано в некоторых комментариях), реализация java.io.OutputStream::close() по умолчанию не вызывает call flush(). Фактически, он ничего не делает. Если у вас есть дистрибутив источника, вы можете легко проверить его сами, иначе просто доверяйте официальному javadoc , указанному здесь:

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

Метод close для OutputStream ничего не делает.

Независимо от того, сбрасывается ли close() или нет, самым безопасным подходом должно быть ручное ручное управление. Если он снова вспыхнет, кому это нужно?

Ответ "Tom Hawtin - tackline" содержит дополнительную информацию о безопасном закрытии потоков (но на самом деле не отвечает на исходный вопрос четко = P).

Ответ 4

Здесь так много опасных ответов и комментариев. Продолжайте читать, почему я использовал слово "опасно".

Прежде всего. Проверьте их.

Вы обнаружите, что нет единственного утверждения, что выражение close() будет вызывать flush(). Исправьте меня, если я пропустил.

Используйте flush(), когда вам нужно или нужно гарантировать сброс буферизованных данных по крайней мере на уровень ОС.

flush() имеет свои собственные цели.

// client
// sends exactly 234 bytes
// and returns exactly 124 bytes from the server
static byte[] sendAndReceive(final OutputStream output,
                             final InputStream input)
    throws IOException {
    final byte[] request = new byte[234];
    output.write(request);
    // output.flush(); // @@? is this required or not?
    final byte[] response = new byte[124];
    new DataInputStream(input).readFully(response);
    return response;
}

// server
// recieve exactly 234 bytes from the client
// sends exactly 124 bytes
static void receiveAndSend(final InputStream input,
                           final OutputStream output)
    throws IOException {
    final byte[] request = new byte[234];
    new DataInputStream(input).readFully(request);
    final byte[] response = new byte[124];
    output.write(response);
    // output.flush(); // @@? is this required or not?
}

Вещи, возможно, были изменены, но я испытал для себя около десяти лет назад. Над исходным кодом (клиент) работал с Windows XP и не удался с Windows 2000 Server для одной и той же конечной точки (сервера).

И (вы) не должны (полагаться) на какое-либо поведение, специфичное для реализации close().

static void writeFile(File file, byte[] bytes) throws IOException {
    try (OutputStream out = new FileOutputStream(bytes)) {
        out.write(bytes);
        out.flush(); // who cares what FileInputStream#close does?
    }
}

Обратите также внимание на то, что flush() не означает запись/отправку ваших данных на физический диск или удаленную конечную точку. Это, в основном, просто очищает буферизованные данные в JVM в базовую ОС.


опечаток

Writer#close() явно говорит, что он

закрывает поток, сначала промывая его.

Но это не значит, что все подклассы сохраняют этот корневой контракт. См. PrintWriter#close(), который (без flush()) закрывает внутренний out (Writer), который, опять же, зависит от параметра out close().

Ответ 5

Потоки представляют ресурсы, которые вы должны всегда очищать явно, вызывая метод close. Некоторые классы java.io(по-видимому, только выходные классы) включают метод flush. Когда метод закрыть вызывается в таком классе, он автоматически выполняет флеш. Нет необходимости явно вызывать flush перед вызовом close.