Исправление ошибки: не удалось прослушать localhost:8000
(причина: адрес уже используется)
ps -ef | grep php
501 **9347** 393 0 1:29PM ttys000 0:00.21 php artisan serve
501 9351 **9347** 0 1:29PM ttys000 0:02.01 /usr/local/php5-5.6.14-20151002-085853/bin/php -S localhost:8000 .../laravel/server.php
501 9781 393 0 1:56PM ttys000 0:00.00 grep php
kill -9 9347
Обычно я делаю следующее. Во-первых, определите класс на основе шаблонного метода для работы с беспорядком try / catch
import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public abstract class AutoFileCloser {
// the core action code that the implementer wants to run
protected abstract void doWork() throws Throwable;
// track a list of closeable thingies to close when finished
private List<Closeable> closeables_ = new LinkedList<Closeable>();
// give the implementer a way to track things to close
// assumes this is called in order for nested closeables,
// inner-most to outer-most
protected final <T extends Closeable> T autoClose(T closeable) {
closeables_.add(0, closeable);
return closeable;
}
public AutoFileCloser() {
// a variable to track a "meaningful" exception, in case
// a close() throws an exception
Throwable pending = null;
try {
doWork(); // do the real work
} catch (Throwable throwable) {
pending = throwable;
} finally {
// close the watched streams
for (Closeable closeable : closeables_) {
if (closeable != null) {
try {
closeable.close();
} catch (Throwable throwable) {
if (pending == null) {
pending = throwable;
}
}
}
}
// if we had a pending exception, rethrow it
// this is necessary b/c the close can throw an
// exception, which would remove the pending
// status of any exception thrown in the try block
if (pending != null) {
if (pending instanceof RuntimeException) {
throw (RuntimeException) pending;
} else {
throw new RuntimeException(pending);
}
}
}
}
}
. Обратите внимание на «ожидающее» исключение - это касается случая, когда исключение, созданное во время закрытия, замаскирует исключение, которое действительно может нас волновать.
Наконец, сначала пытается закрыть снаружи любой декорированный поток, поэтому, если у вас был BufferedWriter, оборачивающий FileWriter, мы сначала пытаемся закрыть BuffereredWriter, а если это не удается, все равно пытаемся закрыть сам FileWriter. (Обратите внимание, что определение Closeable вызывает close () для игнорирования вызова, если поток уже закрыт)
Вы можете использовать приведенный выше класс следующим образом:
try {
// ...
new AutoFileCloser() {
@Override protected void doWork() throws Throwable {
// declare variables for the readers and "watch" them
FileReader fileReader =
autoClose(fileReader = new FileReader("somefile"));
BufferedReader bufferedReader =
autoClose(bufferedReader = new BufferedReader(fileReader));
// ... do something with bufferedReader
// if you need more than one reader or writer
FileWriter fileWriter =
autoClose(fileWriter = new FileWriter("someOtherFile"));
BufferedWriter bufferedWriter =
autoClose(bufferedWriter = new BufferedWriter(fileWriter));
// ... do something with bufferedWriter
}
};
// .. other logic, maybe more AutoFileClosers
} catch (RuntimeException e) {
// report or log the exception
}
Используя этот подход, вам никогда не придется беспокоиться о try / catch / finally, чтобы снова разобраться с закрытием файлов.
Если это слишком сложно для вашего использования,
Это на удивление неудобный вопрос. (Даже если предположить, что получить; попробовать {использовать;} finally {release;} код
верен.)
Если конструкция декоратора завершится неудачно, то вы не закроете базовый поток. Поэтому вам нужно явно закрыть базовый поток, будь то в конце после использования или, что еще сложнее, после успешной передачи ресурса декоратору).
Если исключение вызывает сбой выполнения, вы действительно хотите сбросить?
У некоторых декораторов есть ресурсы. Текущая реализация Sun ZipInputStream
, например, имеет выделенную память кучи, отличную от Java.
Было заявлено, что (IIRC) две трети ресурсов, используемых в библиотеке Java, реализованы явно неправильным образом .
В то время как BufferedOutputStream
закрывается даже при IOException
из flush
, BufferedWriter
закрывается правильно.
Мой совет: Закройте ресурсы как напрямую, насколько это возможно, и не позволяйте им портить другой код. OTOH, вы можете потратить слишком много времени на эту проблему - если выдается OutOfMemoryError
, неплохо вести себя прилично, но другие аспекты вашей программы, вероятно, имеют более высокий приоритет, и код библиотеки, вероятно, в этой ситуации все равно сломан. Но я всегда писал:
final FileOutputStream rawOut = new FileOutputStream(file);
try {
OutputStream out = new BufferedOutputStream(rawOut);
... write stuff out ...
out.flush();
} finally {
rawOut.close();
}
(Смотрите: без уловки!)
И, возможно, использовал идиому Execute Around.
не позволять им портить другой код. OTOH, вы можете потратить слишком много времени на эту проблему - если выдается OutOfMemoryError
, неплохо вести себя прилично, но другие аспекты вашей программы, вероятно, имеют более высокий приоритет, и код библиотеки, вероятно, в этой ситуации все равно сломан. Но я всегда писал:
final FileOutputStream rawOut = new FileOutputStream(file);
try {
OutputStream out = new BufferedOutputStream(rawOut);
... write stuff out ...
out.flush();
} finally {
rawOut.close();
}
(Смотрите: без уловки!)
И, возможно, использовал идиому Execute Around.
не позволять им портить другой код. OTOH, вы можете потратить слишком много времени на эту проблему - если выдается OutOfMemoryError
, неплохо вести себя прилично, но другие аспекты вашей программы, вероятно, имеют более высокий приоритет, и код библиотеки, вероятно, в этой ситуации все равно сломан. Но я всегда писал:
final FileOutputStream rawOut = new FileOutputStream(file);
try {
OutputStream out = new BufferedOutputStream(rawOut);
... write stuff out ...
out.flush();
} finally {
rawOut.close();
}
(Смотрите: без уловки!)
И, возможно, использовал идиому Execute Around.
Sun's JavaDocs include RuntimeException
s in their documentation, as shown by InputStream's read(byte[], int, int) method; documented as throwing NullPointerException and IndexOutOfBoundsException.
FilterOutputStream's flush() is only documented as throwing IOException, thus it doesn't actually throw any RuntimeException
s. Any that could be thrown would most likely be wrapped in an IIOException
.
It could still throw an Error
, but there's not much you can do about those; Sun recommends that you don't try to catch them.
При закрытии связанных потоков вам нужно только закрыть самый внешний поток. Любые ошибки будут распространяться вверх по цепочке и обнаруживаться.
Подробнее см. Потоки ввода-вывода Java .
Для решения проблемы
Однако, если flush () вызывает среду выполнения исключение по какой-то причине, то out.close () никогда не будет вызываться.
Это неправильно. После того, как вы поймаете и проигнорируете это исключение, выполнение возобновится после блока catch, и будет выполнен оператор out.close ()
.
Ваш коллега хорошо подмечает исключение Runtime Exception. Если вам абсолютно необходимо, чтобы поток был закрыт, вы всегда можете попробовать закрыть каждый из них по отдельности, извне внутрь, останавливаясь при первом исключении.
Коллега поднимает интересный вопрос, и есть основания для возражений в любом случае.
Лично я бы проигнорировал RuntimeException
, потому что непроверенное исключение означает ошибку в программе. Если программа некорректна, исправьте. Вы не можете "обработать" плохую программу во время выполнения.