2011-02-05 19 views
12

Podczas odczytu z pliku tekstowego zwykle tworzy się FileReader, a następnie umieszcza się go w BufferedReader. Który z dwóch czytelników powinien się zamknąć, gdy skończę czytać? Czy to ma znaczenie?Zamykanie zagnieżdżonego czytnika

FileReader fr = null; 
BufferedReader br = null; 
try 
{ 
    fr = new FileReader(fileName); 
    br = new BufferedReader(fr); 
    // ... 
} 
finally 
{ 
    // should I close fr or br here? 
} 

Jestem trochę paranoikiem, jeśli chodzi o wyjątki - bezpieczeństwo. Co się dzieje, gdy konstruktor BufferedReader zgłasza wyjątek? Czy zamyka zagnieżdżony czytnik? Czy jest to gwarantowane, że nie rzucisz?

Odpowiedz

9

Ogólnie rzecz biorąc, close() na zewnętrznym opakowaniu strumienia będzie wywoływać close() na owiniętych strumieniach. Jeśli jednak uważasz, że prawdopodobnie konstruktor rzuci wyjątek, zastosuj liberalnie interfejs Closeable.

Tak więc, nawet jeśli JVM zabrakło miejsca na sterty dla bufora i wystąpił błąd, nie wyciekłaby uchwyt pliku.

Dla Java 7 i powyżej użytku try-with-zasobów:

try (FileReader fr = new FileReader(fileName); 
    BufferedReader br = new BufferedReader(fr)) { 
    // do work 
} 
+1

+1. O wiele bardziej elegancko niż moje rozwiązanie. –

+0

Dobre rozwiązanie, jeśli pracujesz z wieloma możliwymi opakowaniami do rzucania wyjątków (i podobnymi). Oczywiście, możesz sprawdzić dokumentację i kod 'BufferedReader', aby sprawdzić, czy istnieje jakakolwiek szansa na wyjątek w ctor. – fwielstra

0

Zamknięcie tylko BufferedReader wystarczy, ponieważ zawija FileReader. Jeśli spojrzysz na source code z zobaczysz, że metoda close zamyka zawinięty strumień.

+0

'buf = new char [8192];' Ew, magiczna liczba! – fredoverflow

0

Zamknij BufferedReader w bloku finally.

0

Jeśli zadzwonisz blisko metoda na BufferedReader, tym BufferedReader wezwie ścisłą metodę FileReader użytkownika. Tak więc są wywoływane obie metody close. Dokładniej, BufferedReader nie zrobi nic, ALE wywołanie metody zamykającej FileReadera. Tak więc to nie ma znaczenia. Chociaż uważam, że jest to dobra praktyka, nazwijmy ją metodą bliską BufferedReader.

0

Nic nie gwarantuje, że się nie wyrzuci. Ponieważ bufor jest przydzielony, może wyrzucić OutOfMemoryError. Zazwyczaj mój kod dzielę na dwie sekcje: pozyskuję zasoby, a następnie korzystam z zasobów. Każda sekcja ma zwykle niepowtarzalny porządki potrzebuje

Oto kod do zilustrowania:

// Acquire resources section. 

final FileReader fr = new FileReader(fileName); 

BufferedReader br = null; 

try 
{ 
    br = new BufferedReader(fr); 
} 
finally 
{ 
    if (br == null) 
    { 
     // Note that you are closing the fr here 
     fr.close(); 
    } 
} 

// Use resources section 
try 
{ 
    // ... use br 
} 
finally 
{ 
    // Now that br is safely constructed, just all its close 
    br.close(); 
} 

I zgadzam się z tobą, nie ma nic warte niż cicho uderzeniem obsługi plików w aplikacji serwera długim biegu.