2010-09-02 5 views
44

Zastanawiam się, czy istnieje potrzeba zamknięcia programu InputStream po zamknięciu czytnika?Czy muszę zamknąć InputStream po zamknięciu czytnika Reader

try { 
     inputStream = new java.io.FileInputStream(file); 
     reader = new InputStreamReader(inputStream, Charset.forName("UTF-8")); 
    } 
    catch (Exception exp) { 
     log.error(null, exp); 
    } 
    finally { 
     if (false == close(reader)) { 
      return null; 
     } 
     // Do I need to close inputStream as well? 
     if (false == close(inputStream)) { 
      return null; 
     } 
    } 
+23

Proszę użyć 'if (!zamknij (czytnik) 'i nie' if (false == close (reader)) ' –

+4

@ Tomak - Tomak - DLACZEGO ?! Mam bardzo słaby wzrok. "false" zajmuje więcej miejsca na ekranie niż "!". To przynajmniej sprawi, że będę bardziej czytelny. –

+9

@Yan Cheng CHEOK to kiepski styl i znacznie trudniejsze do odczytania dla następnej osoby, która odczyta kod. Jeśli masz problemy ze zobaczeniem!, Musisz zwiększyć rozmiar czcionki komputera lub uzyskać mocniejsze okulary, a nie tworzyć własnej konwencji kodowania. – bwawok

Odpowiedz

41

Nie, nie trzeba.

Ponieważ metoda dekoratora używana w przypadku strumieni w języku Java może tworzyć nowe strumienie lub czytniki, dołączając je do innych, będzie to automatycznie obsługiwane przez implementację InputStreamReader.

Jeśli spojrzeć na źródła InputStreamReader.java widać, że:

private final StreamDecoder sd; 

public InputStreamReader(InputStream in) { 
    ... 
    sd = StreamDecoder.forInputStreamReader(in, this, (String)null); 
    ... 
} 

public void close() throws IOException { 
    sd.close(); 
} 

Więc operacja zamykania faktycznie zamyka InputStream bazowego czytnik strumienia.

EDYCJA: Chcę się upewnić, że zamknięcie StreamDecoder działa również w strumieniu wejściowym, bądź na bieżąco.

sprawdzone go w StreamDecoder.java

void implClose() throws IOException { 
    if (ch != null) 
    ch.close(); 
    else 
    in.close(); 
} 

która jest wywoływana, gdy blisko SD nazywa.

+0

A kod każdego z konkretnych StreamDecoders również zamyka bazowy strumień danych, do którego wywoływana jest sd.close() ;-) – helios

+0

Czy powoduje jakiekolwiek szkody, jeśli zamknę plik inputStream? –

+2

Czy znalazłeś to wyraźnie napisane w dokumentacji? Nie jestem pewien, czy jest to ograniczenie dla wszystkich implementacji Javy. @Yan Cheng CHEOK: Jeśli zamkniesz strumień wejściowy po zamknięciu czytnika, nie zaszkodzi. –

3

Nie, nie czytelnik będzie zamknąć bazowego InputStream

0

Acordding do źródła wąchania czytnika zamyka jego podstawowy strumień wejściowy. Zgodnie z javadoc to szwy, że InputStreamReader "zamyka strumień", gdy wywoływane jest read.close().

Nie jestem pewien, czy DOWOLNY Czytelnik musi zamknąć swoje źródła, kiedy robisz read.close(). Myślę, że jest to ważne, aby twój kod mógł korzystać z czytnika bez względu na jego konkretny typ.

W każdym razie ma sens, że jest egzekwowany.

5

Nie musisz zamykać strumienia, jeśli czytasz, close().

Zamyka strumień i zwalnia wszystkie zasoby systemowe związane z go. Gdy strumień zostanie zamknięty, dalsze wywoływanie funkcji read(), ready(), mark(), reset() lub skip() spowoduje zgłoszenie wyjątku IOException. Zamykanie wcześniej zamkniętego strumienia nie ma żadnego efektu.

+0

Reformatowany link; proszę cofnąć, jeśli jest niepoprawna. – trashgod

8

Technicznie zamknięcie Reader spowoduje zamknięcie InputStream. Jeśli jednak wystąpiła awaria między otwarciem InputStream i utworzeniem Reader, nadal należy zamknąć InputStream. Jeśli zamkniesz InputStream [zasób], nie powinno być dobrego powodu, aby zamknąć Reader [dekorator]. Istnieją również popularne błędy, w których zamykanie dekoratora może rzucić wyjątek przed zamknięciem dekorowanego. A więc:

Resource resource = acquire(); 
try { 
    Decorator decorated = decorate(resource); 
    use(decorated); 
} finally { 
    resource.release(); 
} 

Istnieje kilka komplikacji, na które należy zwrócić uwagę. Niektórzy dekoratorzy mogą faktycznie zawierać zasoby natywne ze względu na ich implementację. Dekoratory wyjściowe będą zazwyczaj musiały być przepłukiwane, ale tylko w szczęśliwym przypadku (tak w bloku, a nie w bloku finally).

+2

To się nie powiedzie, jeśli 'Dekorator' jest na przykład' BufferedWriter'. Nigdzie wyraźnie nie udokumentowano, że programista powinien jawnie nazwać 'flush()' po użyciu. – BalusC

+0

@BalusC Jestem zdezorientowany. Pierwszy wiersz dokumentów API "BufferedWriter' mówi, że buforuje znaki. –

+0

'BufferedWriter' (decorated) będzie' flush() 'on' close() '. Na przykład 'FileWriter' (resource) tego nie robi. A więc ryzykujesz nieużywane znaki, gdy zamykasz tylko 'FileWriter' – BalusC

Powiązane problemy