Zamykanie pliku Java
W porządku, robię co następuje (nazwy zmiennych zostały zmienione):
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... handle error ...
}
finally
{
if (fis != null)
fis.close();
}
Ostatnio zacząłem używać FindBugs, co sugeruje, że nie zamykam poprawnie strumieni. Postanawiam sprawdzić, czy jest coś, co można zrobić za pomocą bloku finally {}, a potem widzę, o tak, close() może rzucić IOException. Co ludzie mają tu robić? Biblioteki Javy rzucają zbyt wiele sprawdzonych WYJĄTKÓW.
9 answers
Dla Javy 7 i nowszych try-with-resources należy użyć:
try (InputStream in = new FileInputStream(file)) {
// TODO: work
} catch (IOException e) {
// TODO: handle error
}
Jeśli utkniesz na Javie 6 lub poniżej...
Ten wzorzec pozwala uniknąć zaznaczenia null :
try {
InputStream in = new FileInputStream(file);
try {
// TODO: work
} finally {
in.close();
}
} catch (IOException e) {
// TODO: error handling
}
Aby dowiedzieć się więcej o tym, jak skutecznie radzić sobie z Zamknij, przeczytaj ten wpis na blogu: Java: jak nie robić bałaganu w obsłudze strumienia. Ma więcej przykładowego kodu, większą głębokość i obejmuje pułapki owijania Zamknij w bloku catch.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-10 19:59:31
Coś takiego jak poniżej powinno to zrobić, od ciebie, czy rzucasz lub połykasz IOException przy próbie zamknięcia strumienia.
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... blah blah blah ...
}
finally
{
try
{
if (fis != null)
fis.close();
}
catch (IOException e)
{
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 07:05:57
Możesz użyć try-with-resources funkcja dodana JDK7. Został stworzony właśnie po to, aby radzić sobie z tego rodzaju rzeczami
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
Dokument mówi:
Instrukcja try-with-resources zapewnia zamknięcie każdego Zasobu na końcu Oświadczenia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 22:35:30
Możesz również użyć prostej statycznej metody pomocniczej:
public static void closeQuietly(InputStream s) {
if (null == s) {
return;
}
try {
s.close();
} catch (IOException ioe) {
//ignore exception
}
}
I użyj tego z twojego bloku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 15:35:40
Nic dodać nic ująć, poza bardzo drobną sugestią stylistyczną. kanoniczny przykład samodokumentującego się kodu ma zastosowanie w tym przypadku-podaj opisową nazwę zmiennej ignorowanej IOException
, którą musisz złapać close()
.
Więc odpowiedź squiddle ' a staje się:
public static void closeQuietly(InputStream s) {
try {
s.close();
} catch (IOException ignored) {
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 08:12:45
W większości przypadków uważam, że po prostu lepiej Nie złapać wyjątki IO i po prostu użyć try-finally:
final InputStream is = ... // (assuming some construction that can't return null)
try {
// process is
...
} finally {
is.close();
}
Z wyjątkiem FileNotFoundException
, generalnie nie można "obejść" IOException
. Jedyne, co pozostało do zrobienia, to zgłosić błąd, i zazwyczaj będzie obsługiwać, że dalej w górę stosu połączeń, więc uważam, że lepiej propagować wyjątek.
Ponieważ IOException
jest zaznaczonym wyjątkiem, musisz zadeklarować, że ten kod (i każdy z jego klientów) throws IOException
. To może być zbyt głośny, albo możesz nie chcieć ujawniać szczegółów implementacji korzystania z IO. W takim przypadku można zawinąć cały blok za pomocą funkcji obsługi wyjątków, która zawija {[2] } W typ RuntimeException
lub abstrakcyjny typ wyjątku.
Detail: zdaję sobie sprawę, że powyższy kod pochłania każdy wyjątek z bloku try
, gdy operacja close
w bloku finally
daje IOException
. Nie sądzę, żeby to był duży problem. generalnie wyjątek od bloku try
będzie taki sam IOException
, że powoduje awarię close
(tzn. dość rzadko IO działa poprawnie, a następnie zawodzi w punkcie zamknięcia). Jeśli jest to problemem, może warto "uciszyć" bliskie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 10:52:02
Poniższe rozwiązanie poprawnie wyświetla wyjątek, jeśli close nie powiedzie się bez ukrywania możliwego wyjątku przed zamknięciem.
try {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
} catch(IOException exc) {
// kernel panic
}
To działa, ponieważ wywołanie close po raz drugi nie ma żadnego efektu .
Opiera się to na guava Closeables , ale można napisać własną metodę closeQuietly, jeśli jest to preferowane, jak pokazano w squiddle (Zobacz też serg10).
Zgłaszanie błędu close, w ogólnym przypadku, jest ważne, ponieważ close może napisać kilka końcowe bajty do strumienia, np. z powodu buforowania. Dlatego twój użytkownik chce wiedzieć, czy się nie powiodło, czy prawdopodobnie chcesz jakoś działać. Przyznam, że może to nie być prawda w konkretnym przypadku strumienia Plików, Nie wiem (ale z powodów już wymienionych myślę, że lepiej jest zgłosić Bliski błąd, jeśli i tak wystąpi).
Powyższy kod jest nieco trudny do uchwycenia ze względu na strukturę osadzonych bloków try. Można to uznać za jaśniejsze z dwóch metod, jeden, który rzuca IOException i taki, który go łapie. Przynajmniej na to bym się zdecydował.
private void work() throws IOException {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
}
public void workAndDealWithException() {
try {
work();
} catch(IOException exc) {
// kernel panic
}
}
Na podstawie http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html{[6] / align = "left"/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:59
Miejmy nadzieję, że pewnego dnia będziemy mieć zamknięcia w Javie, a potem stracimy wiele słowności.
Więc zamiast tego w javaIO będzie jakaś metoda pomocnicza, którą możesz zaimportować, prawdopodobnie będzie to wymagało" zamkniętego " interfejsu, a także bloku. Wewnątrz tej metody pomocniczej TRY {closable.close ()} catch (IOException ex) {//bla} jest zdefiniowany raz na zawsze, a wtedy będziesz mógł napisać
Inputstream s = ....;
withClosable(s) {
//your code here
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-01 07:18:51
Czy interesuje Cię przede wszystkim uzyskanie czystego raportu z FindBugs lub posiadanie kodu, który działa? To niekoniecznie to samo. Twój oryginalny kod jest w porządku (chociaż pozbyłbym się zbędnego czeku if (fis != null)
, ponieważ OutOfMemoryException
zostałby wyrzucony w przeciwnym razie). FileInputStream ma metodę finalizera, która zamknie strumień dla Ciebie w mało prawdopodobnym przypadku, gdy faktycznie otrzymasz IOException w przetwarzaniu. Po prostu nie warto się trudzić, aby Twój kod był bardziej wyrafinowane, aby uniknąć niezwykle nieprawdopodobnego scenariusza
- otrzymujesz IOException i
- zdarza się to tak często, że pojawiają się problemy z zaległościami finalizera.
Edit: jeśli dostajesz tak wiele IOExceptions, że masz problemy z kolejką finalizera, to masz o wiele większe ryby do usmażenia! Chodzi o uzyskanie poczucia perspektywy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-07 10:15:01