Java BufferedWriter close () - PullRequest
       16

Java BufferedWriter close ()

4 голосов
/ 02 июня 2010

Предположим, у меня есть следующий фрагмент кода:

operation1();
bw.close();
operation2();

Когда я вызываю BufferedReader.close() из своего кода, я предполагаю, что моя JVM выполняет системный вызов, который гарантирует, что буфер был очищен и записан на диск. Я хочу знать, ждет ли close(), пока системный вызов завершит свою работу, или он переходит к operation2(), не дожидаясь завершения close().

Если перефразировать мой вопрос, когда я наберу operation2(), могу ли я предположить, что bw.close() успешно завершен?

Ответы [ 8 ]

5 голосов
/ 02 июня 2010

Когда я выполняю операцию 2 (), могу ли я предположить, что bw.close () успешно завершена?

Да

4 голосов
/ 02 июня 2010

JavaDoc для java.io.BufferedReader.close() берется именно из контракта, если выполняется с java.io.Reader.

Док говорит:

Закрывает поток и освобождает любые системные ресурсы, связанные с ним. Как только поток будет закрыт, дальнейшие вызовы read (), ready (), mark (), reset () или skip () вызовут IOException. Закрытие ранее закрытого потока не имеет никакого эффекта.

Несмотря на то, что это не делает явных заявлений о блокировке, пока файловая система не будет завершена, с этим же экземпляром BufferedReader все другие операции будут выдавать исключение, если close() вернется. Хотя JavaDoc может показаться неоднозначным в отношении того, когда операция завершается, если очистка и закрытие файловой системы не были завершены, когда этот метод возвращался, это нарушило бы дух контракта и было бы ошибкой в ​​Java (реализация или документация).

4 голосов
/ 02 июня 2010

Закройте поток, сначала очистив его. Когда поток будет закрыт, дальнейшие вызовы write () или flush () вызовут IOException. Однако закрытие ранее закрытого потока не имеет никакого эффекта.

Хотя в документации ничего не сказано конкретно, я бы предположил, что этот вызов блокирует до завершения. На самом деле, я уверен, что в пакете java.io нет ничего неблокирующего.

2 голосов
/ 02 июня 2010

НЕТ! Вы не можете быть уверены по следующей причине:

BufferedWriter - это оболочка для другого писателя. Функция close () для BufferedWriter просто распространяется на базовый модуль записи.

ЕСЛИ этот лежащий в основе Writer является OutputStreamWriter, а ЕСЛИ OutputStream является FileOutputStream, то после закрытия будет выполнен системный вызов для закрытия дескриптора файла.

Вы совершенно свободны даже для Writer, где close () является noop, или где close реализован неблокирующим, но при использовании только классов из java.io это никогда не происходит.

1 голос
/ 03 июня 2010

Буфер будет сброшен в операционную систему, а дескриптор файла закрыт, поэтому требуемые операции Java будут завершены.

НО операционная система кэширует или ставит в очередь запись на фактический диск, канал, сеть, что угодно - нет никакой гарантии, что физическая запись завершена. FileChannel.force () предоставляет способ сделать это для файлов на локальных дисках: см. Javadoc.

1 голос
/ 02 июня 2010

В целом, при любой операции ввода-вывода вы не можете делать предположений о том, что произошло после завершения операции write(), даже после того, как вы close. Идея delivery является субъективным понятием относительно среды.

Например, что если writer представляет собой соединение TCP, а затем данные теряются между клиентом и сервером? Или что, если ядро ​​записывает данные на диск, но диск физически не может записать его? Или, если автор представляет почтового голубя, которого застрелят в пути?

Кроме того, представьте себе случай, когда запись не может подтвердить, что конечная точка получила данные (читай: udp / дейтаграммы). Какой должна быть политика блокировки в этой ситуации?

1 голос
/ 02 июня 2010

A Writer (или BufferedWriter) - это черный ящик, который записывает поток символов куда-то, не обязательно на диск. Вызов close() должен (по контракту метода) очистить буферизованное содержимое перед закрытием, а должен (обычно) заблокировать перед всей своей "существенной" работой готово. Но это будет зависеть от реализации и среды (например, вы не можете знать о кешах, которые находятся ниже уровня Java). Что касается работы, выполняемой самим Java-писателем (например, сделать системный вызов для записи на диск, в случае FileWriter или подобный, и закрыть дескриптор файла), да, вы можете предположить, что когда close() возвращает, он уже сделал всю свою работу.

0 голосов
/ 02 июня 2010

Да, ЕСЛИ вы достигнете operation2();, поток должен был бы быть полностью закрыт. Тем не менее, close() throws IOException, так что вы можете даже не добраться до operation2();. Это может или не может быть поведение, которое вы ожидаете.

...